gltail 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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