gltail 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,194 @@
1
+ # gl_tail.rb - OpenGL visualization of your server traffic
2
+ # Copyright 2007 Erlend Simonsen <mr@fudgie.org>
3
+ #
4
+ # Licensed under the GNU General Public License v2 (see LICENSE)
5
+ #
6
+
7
+ class Element
8
+ attr_accessor :wy, :y, :active, :average_size, :right, :color, :name
9
+ attr_reader :rate, :messages, :activities, :queue, :updates, :average, :total
10
+
11
+ def initialize(block, name, start_position = nil)
12
+ @block = block
13
+
14
+ if name =~ /^\d+.\d+.\d+.\d+$/
15
+ @name = Resolver.resolv(name, self)
16
+ else
17
+ @name = name
18
+ end
19
+
20
+ @start_position = start_position.nil? ? -@block.top : start_position
21
+
22
+ @queue = []
23
+ @pending = []
24
+ @activities = []
25
+ @messages = 0
26
+ @rate = 0
27
+ @total = 0
28
+ @sum = 0
29
+ @average = 0.0
30
+ @last_time = 0
31
+ @step = 0, @updates = 0
32
+ @active = false
33
+ end
34
+
35
+ def add_activity(message, color, size, type)
36
+ @pending.push Item.new(message, size, color, type) if(type != 3)
37
+ @messages += 1
38
+ @sum += size
39
+ @color = color
40
+
41
+ if @rate == 0
42
+ @rate = 1.0 / 60
43
+ @messages = 0
44
+ end
45
+ end
46
+
47
+ def add_event(message, color, update_stats)
48
+ @pending.push Item.new(message, 0.01, color, 2)
49
+ if update_stats
50
+ @messages += 1
51
+ if @rate == 0
52
+ @rate = 1.0 / 60
53
+ @messages = 0
54
+ end
55
+ end
56
+ end
57
+
58
+
59
+ def update
60
+ @active = true if @total > 0
61
+ @updates += 1
62
+ @rate = (@rate.to_f * 299 + @messages) / 300
63
+ @messages = 0
64
+ if @pending.size + @queue.size > 0
65
+ @total += @pending.size
66
+ @average = @sum / @total
67
+
68
+ @step = 1.0 / (@queue.size + @pending.size) * 1000.0
69
+ @queue = @queue + @pending
70
+ if @queue.size == 1
71
+ @step = rand(1000) * 1.0
72
+ end
73
+ @pending = []
74
+ else
75
+ @step = 0
76
+ end
77
+ @last_time = glutGet(GLUT_ELAPSED_TIME)
78
+ @last_time += @step if @queue.size == 1
79
+ # @last_time -= @step if @queue.size != 1
80
+
81
+
82
+ end
83
+
84
+ def render(engine, options = { })
85
+
86
+ # this used to be in the constructor, couldnt leave it there without using globals
87
+ if not defined? @x
88
+ @x = (@block.is_right ? @block.alignment : (@block.alignment - (8.0 / (@block.config.screen.window_width / 2.0)) * (@block.width + 8)))
89
+ @y = @start_position
90
+ @z = 0
91
+ @wy = @start_position
92
+
93
+ @color = @block.color.dup if @color.nil? && @block.color
94
+ @color ||= [1.0, 1.0, 1.0, 1.0]
95
+ @size = 0.01
96
+ end
97
+
98
+ @wx = @block.is_right ? (@block.alignment - (@block.width+8)*8.0 / (engine.screen.window_width / 2.0)) : @block.alignment
99
+
100
+ if(@y == -@block.top)
101
+ @y = @wy
102
+ end
103
+
104
+ d = @wy - @y
105
+ if d.abs < 0.001
106
+ @y = @wy
107
+ else
108
+ @y += d / 20
109
+ end
110
+
111
+ d = @wx - @x
112
+ if d.abs < 0.001
113
+ @x = @wx
114
+ else
115
+ @x += d / 20
116
+ end
117
+
118
+ glPushMatrix()
119
+
120
+ glTranslate(@x, @y, @z)
121
+
122
+ glColor( (@queue.size > 0 ? (engine.screen.highlight_color || [1.0, 0.0, 0.0, 1.0]) : @color ) )
123
+
124
+ case @block.show
125
+ when 0
126
+ if @rate < 0.0001
127
+ txt = " r/m "
128
+ else
129
+ txt = "#{sprintf("%7.2f",@rate * 60)} "
130
+ end
131
+ when 1
132
+ if @total == 0
133
+ txt = " total "
134
+ else
135
+ txt = "#{sprintf("%7d",@total)} "
136
+ end
137
+ when 2
138
+ if @average == 0
139
+ txt = " avg "
140
+ else
141
+ txt = "#{sprintf("%7.2f",@average)} "
142
+ end
143
+ else
144
+ raise "unknown block type #{self.inspect}"
145
+ end
146
+
147
+ if @x < 0
148
+ str = sprintf("%#{@block.width}s %s", @name.length > @block.width ? @name[-@block.width..-1] : @name, txt)
149
+ else
150
+ str = sprintf("%s %s", txt, @name[0..@block.width-1])
151
+ end
152
+
153
+ engine.render_string(str)
154
+
155
+ glPopMatrix()
156
+
157
+ t = glutGet(GLUT_ELAPSED_TIME)
158
+ while( (@queue.size > 0) && (@last_time < t ) )
159
+
160
+ @last_time += @step
161
+ item = @queue.pop
162
+ url = item.message
163
+ color = item.color
164
+ size = item.size
165
+ type = item.type
166
+
167
+ if type == 2
168
+ @activities.push Activity.new(url, 0.0 - (0.013 * url.length), engine.screen.top, 0.0, color, size, type)
169
+ elsif type == 5
170
+ a = Activity.new(url, 0.0, engine.screen.top, 0.0, color, size, type)
171
+ a.wx = @wx
172
+ a.wy = @wy + 0.05
173
+ @activities.push a
174
+ elsif type != 4
175
+ if @x >= 0
176
+ @activities.push Activity.new(url, (@block.alignment - (@block.width+8)*8.0 / (engine.screen.window_width / 2.0)), @y + engine.screen.line_size/2, @z, color, size, type)
177
+ else
178
+ @activities.push Activity.new(url, (@block.alignment + (@block.width+8)*8.0 / (engine.screen.window_width / 2.0) ), @y + engine.screen.line_size/2, @z, color, size, type)
179
+ end
180
+ end
181
+ end
182
+
183
+ @activities.each do |a|
184
+ if a.x > 1.0 || a.x < -1.0 || a.y < -(engine.screen.aspect*1.5)
185
+ @activities.delete a
186
+ else
187
+ a.wy = @wy + 0.005 if(a.type == 5 && @wy != a.wy)
188
+ a.render(engine)
189
+ engine.stats[1] += 1
190
+ end
191
+ end
192
+
193
+ end
194
+ end
@@ -0,0 +1,266 @@
1
+
2
+ include Gl
3
+ include Glut
4
+
5
+ module GlTail
6
+ class Engine
7
+
8
+ def render_string(string)
9
+ FontStore.render_string(self, string)
10
+ end
11
+
12
+ def screen
13
+ @config.screen
14
+ end
15
+
16
+ def char_size
17
+ @char_size ||= (8.0 / (@config.screen.window_width / 2.0))
18
+ end
19
+
20
+ def line_size
21
+ @config.screen.line_size
22
+ end
23
+
24
+ def highlight_color
25
+ @config.screen.highlight_color
26
+ end
27
+
28
+ def reset_stats
29
+ @stats = [0, 0]
30
+ end
31
+
32
+ def stats
33
+ @stats
34
+ end
35
+
36
+ def draw
37
+ @render_time ||= 0
38
+ @t = Time.new
39
+
40
+ glClear(GL_COLOR_BUFFER_BIT);
41
+ # glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
42
+
43
+ glPushMatrix()
44
+
45
+ positions = Hash.new
46
+
47
+ reset_stats
48
+
49
+ glPushMatrix()
50
+
51
+ glColor([0.15, 0.15, 0.15, 1.0])
52
+ glBegin(GL_QUADS)
53
+ glNormal3f(1.0, 1.0, 0.0)
54
+
55
+ glVertex3f(@left_left, @config.screen.aspect, 0.0)
56
+ glVertex3f(@left_right, @config.screen.aspect, 0.0)
57
+ glVertex3f(@left_right, -@config.screen.aspect, 0.0)
58
+ glVertex3f(@left_left, -@config.screen.aspect, 0.0)
59
+
60
+ glVertex3f(@right_left, @config.screen.aspect, 0.0)
61
+ glVertex3f(@right_right, @config.screen.aspect, 0.0)
62
+ glVertex3f(@right_right, -@config.screen.aspect, 0.0)
63
+ glVertex3f(@right_left, -@config.screen.aspect, 0.0)
64
+
65
+ glEnd()
66
+ glPopMatrix()
67
+
68
+ # TODO: do we really need to sort every block on every draw?!
69
+ # Nope. But it was a hash, so keeping order was a bit hard.
70
+ @config.blocks.sort { |k,v| k.order <=> v.order}.each do |block|
71
+ # glPushMatrix + glTranslate3f to render each element relativ to its containing block instead of the screen?
72
+ positions[block.is_right] = block.render(self, positions[block.is_right] || 0 )
73
+ end
74
+
75
+ glPopMatrix()
76
+
77
+ @frames += 1
78
+ t = glutGet(GLUT_ELAPSED_TIME)
79
+ if t - @t0 >= 5000
80
+ seconds = (t - @t0) / 1000.0
81
+ $FPS = @frames / seconds
82
+ printf("%d frames in %6.3f seconds = %6.3f FPS\n",
83
+ @frames, seconds, $FPS) if $VRB > 0
84
+ @t0, @frames = t, 0
85
+ puts "Elements[#{stats[0]}], Activities[#{stats[1]}], Blobs[#{BlobStore.used}/#{BlobStore.size}]" if $VRB > 0
86
+ end
87
+ @render_time = (Time.new - @t)
88
+ end
89
+
90
+ def idle
91
+ @last_run ||= Time.new
92
+ @last_run_time ||= 0
93
+ delta = (Time.new - @last_run) - @last_run_time
94
+ if @config.screen.wanted_fps > 0 && delta < (1000.0/(@config.screen.wanted_fps*1000.0))
95
+ sleep((1000.0/(@config.screen.wanted_fps*1000.0) - delta))
96
+ end
97
+ @last_run = Time.new
98
+ glutPostRedisplay()
99
+ glutSwapBuffers()
100
+ do_process
101
+ @last_run_time = (@last_run_time.to_f * (@config.screen.wanted_fps-1.0) + (Time.new - @last_run).to_f) / @config.screen.wanted_fps.to_f if @config.screen.wanted_fps > 0
102
+ end
103
+
104
+ def timer(value)
105
+ glutTimerFunc(15, method(:timer).to_proc, 0)
106
+ # t = glutGet(GLUT_ELAPSED_TIME)
107
+ glutPostRedisplay()
108
+ glutSwapBuffers()
109
+ do_process
110
+ # t = glutGet(GLUT_ELAPSED_TIME) - t
111
+ # t = 14 if t > 14
112
+ end
113
+
114
+ # Change view angle, exit upon ESC
115
+ def key(k, x, y)
116
+ case k
117
+ when 27 # Escape
118
+ exit
119
+ when 32 # Space
120
+ @config.screen.bounce ||= false
121
+ @config.screen.bounce = !@config.screen.bounce
122
+ when 102 #f
123
+ @config.screen.wanted_fps = case @config.screen.wanted_fps
124
+ when 0
125
+ 60
126
+ when 60
127
+ 50
128
+ when 50
129
+ 45
130
+ when 45
131
+ 30
132
+ when 30
133
+ 25
134
+ when 25
135
+ 20
136
+ when 20
137
+ 0
138
+ end
139
+ puts "WANTED_FPS[#{@config.screen.wanted_fps}]"
140
+ when 98
141
+ @config.screen.mode = 1 - @config.screen.mode.to_i
142
+ BlobStore.empty
143
+ end
144
+ puts "Keypress: #{k}"
145
+ glutPostRedisplay()
146
+ end
147
+
148
+ # Change view angle
149
+ def special(k, x, y)
150
+ glutPostRedisplay()
151
+ end
152
+
153
+ # New window size or exposure
154
+ def reshape(width, height)
155
+ @config.reshape(width, height)
156
+
157
+ # reset char size
158
+ @char_size = nil
159
+
160
+ @left_left = @config.screen.left.alignment + char_size * (@config.screen.left.size + 1)
161
+ @left_right = @config.screen.left.alignment + char_size * (@config.screen.left.size + 8)
162
+
163
+ @right_left = @config.screen.right.alignment - char_size * (@config.screen.right.size + 1)
164
+ @right_right = @config.screen.right.alignment - char_size * (@config.screen.right.size + 8)
165
+
166
+ glViewport(0, 0, width, height)
167
+ glMatrixMode(GL_PROJECTION)
168
+ glLoadIdentity()
169
+
170
+ # glFrustum(-1.0, 1.0, -@config.screen.aspect, @config.screen.aspect, 5.0, 60.0)
171
+ glOrtho(-1.0, 1.0, -@config.screen.aspect, @config.screen.aspect, -1.0, 1.0)
172
+
173
+ @config.screen.line_size = @config.screen.aspect * 2 / (@config.screen.window_height/13.0)
174
+ @config.screen.top = @config.screen.aspect - @config.screen.line_size
175
+
176
+ puts "Reshape: #{width}x#{height} = #{@config.screen.aspect}/#{@config.screen.line_size}" if $VRB > 0
177
+
178
+ glMatrixMode(GL_MODELVIEW)
179
+ glLoadIdentity()
180
+ glTranslate(0.0, 0.0, 0.0)
181
+
182
+ BlobStore.empty # Flush cached objects to recreate with correct size
183
+ end
184
+
185
+ def visible(vis)
186
+ # glutIdleFunc((vis == GLUT_VISIBLE ? method(:idle).to_proc : nil))
187
+ end
188
+
189
+ def mouse(button, state, x, y)
190
+ @mouse = state
191
+ @x0, @y0 = x, y
192
+ end
193
+
194
+ def motion(x, y)
195
+ if @mouse == GLUT_DOWN then
196
+ end
197
+ @x0, @y0 = x, y
198
+ end
199
+
200
+ def initialize(config)
201
+ @config = config
202
+
203
+ @frames = 0
204
+ @t0 = 0
205
+ @left_left = @left_right = @right_left = @right_right = 0.0 # TODO: Why is draw called before these are set by reshape?
206
+ end
207
+
208
+ def start
209
+ glutInit()
210
+ glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE)
211
+
212
+ glutInitWindowPosition(0, 0)
213
+ glutInitWindowSize(@config.screen.window_width, @config.screen.window_height)
214
+ glutCreateWindow('glTail')
215
+
216
+ glutDisplayFunc(method(:draw).to_proc)
217
+ glutReshapeFunc(method(:reshape).to_proc)
218
+ glutKeyboardFunc(method(:key).to_proc)
219
+ glutSpecialFunc(method(:special).to_proc)
220
+ glutVisibilityFunc(method(:visible).to_proc)
221
+ glutMouseFunc(method(:mouse).to_proc)
222
+ glutMotionFunc(method(:motion).to_proc)
223
+
224
+ glutIdleFunc(method(:idle).to_proc)
225
+ # glutTimerFunc(33, method(:timer).to_proc, 0)
226
+
227
+ glLightfv(GL_LIGHT0, GL_POSITION, [5.0, 5.0, 0.0, 0.0])
228
+ glLightfv(GL_LIGHT0, GL_AMBIENT, [0,0,0,1])
229
+ glDisable(GL_CULL_FACE)
230
+ glEnable(GL_LIGHTING)
231
+ glEnable(GL_LIGHT0)
232
+ glEnable(GL_TEXTURE_2D)
233
+ # glShadeModel(GL_FLAT)
234
+ glDisable(GL_DEPTH_TEST)
235
+ glDisable(GL_NORMALIZE)
236
+ # glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST)
237
+ glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST )
238
+
239
+ glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE)
240
+ glEnable(GL_COLOR_MATERIAL)
241
+ glEnable(GL_NORMALIZE)
242
+ FontStore.generate_font
243
+
244
+ @since = glutGet(GLUT_ELAPSED_TIME)
245
+
246
+ @config.init
247
+
248
+ glutMainLoop()
249
+ end
250
+
251
+ def do_process
252
+ active = @config.do_process
253
+
254
+ if active >= 0
255
+
256
+ if glutGet(GLUT_ELAPSED_TIME) - @since >= 1000
257
+ @since = glutGet(GLUT_ELAPSED_TIME)
258
+ @config.update
259
+ BlobStore.prune
260
+ end
261
+ end
262
+
263
+ self
264
+ end
265
+ end
266
+ end