64
+++ puppet-2.7.11/lib/puppet/util/instrumentation/listeners/process_name.rb
68
+# Unlike the other instrumentation plugins, this one doesn't give back
69
+# data. Instead it changes the process name of the currently running process
70
+# with the last labels and data.
71
+Puppet::Util::Instrumentation.new_listener(:process_name) do
74
+ # start scrolling when process name is longer than
77
+ attr_accessor :active, :reason
79
+ def notify(label, event, data)
80
+ start(label) if event == :start
81
+ stop if event == :stop
85
+ push_activity(Thread.current, activity)
89
+ pop_activity(Thread.current)
95
+ @scroller ||= Thread.new do
106
+ $0 = @oldname if @oldname
107
+ Thread.kill(@scroller)
113
+ $0 = "#{base}: " + rotate(process_name,@x)
116
+ def push_activity(thread, activity)
119
+ @reason[thread] ||= []
120
+ @reason[thread].push(activity)
125
+ def pop_activity(thread)
127
+ @reason[thread].pop
128
+ if @reason[thread].empty?
129
+ @reason.delete(thread)
136
+ out = (@reason || {}).inject([]) do |out, reason|
137
+ out << "#{thread_id(reason[0])} #{reason[1].join(',')}"
142
+ # Getting the ruby thread id might not be portable to other ruby
143
+ # interpreters than MRI, because Thread#inspect might not return the same
144
+ # information on a different runtime.
145
+ def thread_id(thread)
146
+ thread.inspect.gsub(/^#<.*:0x([a-f0-9]+) .*>$/, '\1')
149
+ def rotate(string, steps)
151
+ if string.length > 0 && steps > 0
152
+ steps = steps % string.length
153
+ return string[steps..-1].concat " -- #{string[0..(steps-1)]}"
159
+ basename = case Puppet.run_mode.name
171
+ return if process_name.length < SCROLL_LENGTH
178
\ No newline at end of file
179
--- puppet-2.7.11.orig/test/lib/puppettest/fakes.rb
180
+++ puppet-2.7.11/test/lib/puppettest/fakes.rb
182
-require File.expand_path(File.join(File.dirname(__FILE__), '../../../lib/puppet/util'))
183
+require '/usr/lib/ruby/1.8/puppet/util'
186
# A baseclass for the faketypes.
188
+++ puppet-2.7.11/spec/unit/util/instrumentation/listeners/process_name_spec.rb
190
+#!/usr/bin/env rspec
191
+require 'spec_helper'
192
+require 'puppet/util/instrumentation'
194
+Puppet::Util::Instrumentation.init
195
+process_name = Puppet::Util::Instrumentation.listener(:process_name)
197
+describe process_name do
199
+ @process_name = process_name.new
202
+ it "should have a notify method" do
203
+ @process_name.should respond_to(:notify)
206
+ it "should not have a data method" do
207
+ @process_name.should_not respond_to(:data)
210
+ describe "when managing thread activity" do
212
+ @process_name.stubs(:setproctitle)
213
+ @process_name.stubs(:base).returns("base")
216
+ it "should be able to append activity" do
217
+ thread1 = stub 'thread1'
218
+ @process_name.push_activity(:thread1,"activity1")
219
+ @process_name.push_activity(:thread1,"activity2")
221
+ @process_name.reason[:thread1].should == ["activity1", "activity2"]
224
+ it "should be able to remove activity" do
225
+ @process_name.push_activity(:thread1,"activity1")
226
+ @process_name.push_activity(:thread1,"activity1")
227
+ @process_name.pop_activity(:thread1)
229
+ @process_name.reason[:thread1].should == ["activity1"]
232
+ it "should maintain activity thread by thread" do
233
+ @process_name.push_activity(:thread1,"activity1")
234
+ @process_name.push_activity(:thread2,"activity2")
236
+ @process_name.reason[:thread1].should == ["activity1"]
237
+ @process_name.reason[:thread2].should == ["activity2"]
240
+ it "should set process title" do
241
+ @process_name.expects(:setproctitle)
243
+ @process_name.push_activity("thread1","activity1")
247
+ describe "when computing the current process name" do
249
+ @process_name.stubs(:setproctitle)
250
+ @process_name.stubs(:base).returns("base")
253
+ it "should include every running thread activity" do
254
+ thread1 = stub 'thread1', :inspect => "\#<Thread:0xdeadbeef run>", :hash => 1
255
+ thread2 = stub 'thread2', :inspect => "\#<Thread:0x12344321 run>", :hash => 0
257
+ @process_name.push_activity(thread1,"Compiling node1.domain.com")
258
+ @process_name.push_activity(thread2,"Compiling node4.domain.com")
259
+ @process_name.push_activity(thread1,"Parsing file site.pp")
260
+ @process_name.push_activity(thread2,"Parsing file node.pp")
262
+ @process_name.process_name.should =~ /12344321 Compiling node4.domain.com,Parsing file node.pp/
263
+ @process_name.process_name.should =~ /deadbeef Compiling node1.domain.com,Parsing file site.pp/
267
+ describe "when finding base process name" do
268
+ {:master => "master", :agent => "agent", :user => "puppet"}.each do |program,base|
269
+ it "should return #{base} for #{program}" do
270
+ Puppet.run_mode.stubs(:name).returns(program)
271
+ @process_name.base.should == base
276
+ describe "when finding a thread id" do
277
+ it "should return the id from the thread inspect string" do
278
+ thread = stub 'thread', :inspect => "\#<Thread:0x1234abdc run>"
279
+ @process_name.thread_id(thread).should == "1234abdc"
283
+ describe "when scrolling the instrumentation string" do
284
+ it "should rotate the string of various step" do
285
+ @process_name.rotate("this is a rotation", 10).should == "rotation -- this is a "
288
+ it "should not rotate the string for the 0 offset" do
289
+ @process_name.rotate("this is a rotation", 0).should == "this is a rotation"
293
+ describe "when setting process name" do
295
+ @process_name.stubs(:process_name).returns("12345 activity")
296
+ @process_name.stubs(:base).returns("base")
304
+ it "should do it if the feature is enabled" do
305
+ @process_name.setproctitle
307
+ $0.should == "base: 12345 activity"
311
+ describe "when subscribed" do
313
+ thread = stub 'thread', :inspect => "\#<Thread:0x1234abdc run>"
314
+ Thread.stubs(:current).returns(thread)
317
+ it "should start the scroller" do
318
+ Thread.expects(:new)
319
+ @process_name.subscribed
323
+ describe "when unsubscribed" do
325
+ @thread = stub 'scroller', :inspect => "\#<Thread:0x1234abdc run>"
326
+ Thread.stubs(:new).returns(@thread)
327
+ Thread.stubs(:kill)
329
+ @process_name.subscribed
336
+ it "should stop the scroller" do
337
+ Thread.expects(:kill).with(@thread)
338
+ @process_name.unsubscribed
341
+ it "should reset the process name" do
342
+ $0 = "let's see what happens"
343
+ @process_name.unsubscribed
344
+ $0.should == @oldname
348
+ describe "when setting a probe" do
350
+ thread = stub 'thread', :inspect => "\#<Thread:0x1234abdc run>"
351
+ Thread.stubs(:current).returns(thread)
353
+ @process_name.active = true
356
+ it "should push current thread activity and execute the block" do
357
+ @process_name.notify(:instrumentation, :start, {})
358
+ $0.should == "puppet: 1234abdc instrumentation"
359
+ @process_name.notify(:instrumentation, :stop, {})
362
+ it "should finally pop the activity" do
363
+ @process_name.notify(:instrumentation, :start, {})
364
+ @process_name.notify(:instrumentation, :stop, {})
365
+ $0.should == "puppet: "
369
+ describe "when scrolling" do
370
+ it "should do nothing for shorter process names" do
371
+ @process_name.expects(:setproctitle).never
372
+ @process_name.scroll
375
+ it "should call setproctitle" do
376
+ @process_name.stubs(:process_name).returns("x" * 60)
377
+ @process_name.expects(:setproctitle)
378
+ @process_name.scroll
381
+ it "should increment rotation offset" do
383
+ @process_name.stubs(:process_name).returns(name)
384
+ @process_name.expects(:rotate).once.with(name,1).returns("")
385
+ @process_name.expects(:rotate).once.with(name,2).returns("")
386
+ @process_name.scroll
387
+ @process_name.scroll
391
\ No newline at end of file