gltail 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Binary file
@@ -0,0 +1,165 @@
1
+ class FontStore
2
+ @list_base = 0
3
+ @font = []
4
+ @buffers = nil
5
+
6
+ @font_texture = nil
7
+
8
+ def self.generate_textures
9
+ if @font_texture.nil?
10
+ @font_texture = glGenTextures(1)[0]
11
+
12
+ File.open("#{File.dirname(__FILE__)}/font.bin") do |f|
13
+ @font = Marshal.load(f)
14
+ end
15
+
16
+ font_data = []
17
+
18
+ # Add missing pixels to increase height by 3
19
+ 32.upto(255) do |c|
20
+ @font[c] += @font[c] + [0,0,0].pack("C*") * 24
21
+ end
22
+
23
+ 0.upto(196607) do |i|
24
+ font_data[i] = 0
25
+ end
26
+
27
+ # Re-order bitmap data into one 256x256 texture
28
+ 32.upto(255) do |c|
29
+ row = (c - 32) / 16
30
+ col = (c - 32) % 16
31
+
32
+ offset = row * 256*16*3 + col*8*3
33
+ 0.upto(15) do |y|
34
+ 0.upto(7) do |x|
35
+ font_data[offset + y*256*3 + x*3 +0] = @font[c][y*8*3 + x*3 + 0]
36
+ font_data[offset + y*256*3 + x*3 +1] = @font[c][y*8*3 + x*3 + 1]
37
+ font_data[offset + y*256*3 + x*3 +2] = @font[c][y*8*3 + x*3 + 2]
38
+ end
39
+ end
40
+
41
+ end
42
+
43
+ # File.open("lib/font_256.bin", "wb") do |f|
44
+ # Marshal.dump(font_data, f)
45
+ # end
46
+
47
+ font_data = font_data.pack("C*")
48
+
49
+ glBindTexture(GL_TEXTURE_2D, @font_texture)
50
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
51
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
52
+ # glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
53
+ # glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
54
+ # glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
55
+ # glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
56
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)
57
+ # glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL)
58
+ # glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)
59
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, font_data)
60
+
61
+ glBindTexture(GL_TEXTURE_2D, 0)
62
+ end
63
+ end
64
+
65
+ def self.generate_font
66
+ self.generate_textures
67
+ return
68
+
69
+ # Ignore the rest for now, used only to create font.bin
70
+
71
+ # glPushMatrix
72
+ # glViewport(0, 0, 8, 15)
73
+ # glMatrixMode(GL_PROJECTION)
74
+ # glLoadIdentity()
75
+
76
+ # glOrtho(0, 8, 13, 0, -1.0, 1.0)
77
+
78
+ # glMatrixMode(GL_MODELVIEW)
79
+ # glLoadIdentity()
80
+ # glTranslate(0, 0, 0)
81
+
82
+ # glMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, ( [1.0, 1.0, 1.0, 1.0] ) )
83
+ # 32.upto(255) do |c|
84
+ # glClearColor(0.0, 0.0, 0.0, 1.0)
85
+ # glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
86
+
87
+ # glRasterPos(0,0)
88
+ # begin
89
+ # glutBitmapCharacter(GLUT_BITMAP_8_BY_13, c)
90
+ # rescue RangeError
91
+ # glutBitmapCharacterX(c)
92
+ # end
93
+
94
+ # glBindTexture(GL_TEXTURE_2D, @textures[c])
95
+ # glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 13, 8, 13, 0)
96
+
97
+
98
+ # glBindTexture(GL_TEXTURE_2D, 0)
99
+ # end
100
+ # glClearColor(0.0, 0.0, 0.0, 1.0)
101
+ # glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
102
+
103
+ # glPopMatrix
104
+
105
+ end
106
+
107
+ def self.render_char(engine, c, pos)
108
+ char_size = engine.char_size
109
+
110
+ base = c-32
111
+
112
+ offsetx = ((base%16) ) / (32.0)
113
+ offsety = ((base/16) * 16) / (256.0)
114
+
115
+ width = 8 / 256.0
116
+ height = 13 / 256.0
117
+
118
+ pos_offset = char_size * pos
119
+
120
+ glTexCoord2f(offsetx,offsety)
121
+ glNormal3f(1.0, 1.0, 0.0)
122
+ glVertex3f(pos_offset, 0, 0.0)
123
+
124
+ glTexCoord2f(offsetx+width,offsety)
125
+ glNormal3f(1.0, 1.0, 0.0)
126
+ glVertex3f(pos_offset + char_size, 0.0, 0.0)
127
+
128
+ glTexCoord2f(offsetx+width,offsety + height)
129
+ glNormal3f(1.0, 1.0, 0.0)
130
+ glVertex3f(pos_offset + char_size, engine.line_size, 0.0)
131
+
132
+ glTexCoord2f(offsetx,offsety + height)
133
+ glNormal3f(1.0, 1.0, 0.0)
134
+ glVertex3f(pos_offset, engine.line_size, 0.0)
135
+ end
136
+
137
+
138
+ def self.render_string(engine, txt)
139
+ glPushMatrix
140
+ glEnable(GL_BLEND)
141
+ glBlendFunc(GL_ONE, GL_ONE)
142
+ glBindTexture(GL_TEXTURE_2D, @font_texture)
143
+
144
+ unless BlobStore.has(txt)
145
+ list = glGenLists(1)
146
+ glNewList(list, GL_COMPILE)
147
+ glBegin(GL_QUADS)
148
+ pos = 0
149
+ txt.each_byte do |c|
150
+ self.render_char(engine, c, pos)
151
+ pos += 1
152
+ end
153
+ glEnd
154
+ glEndList
155
+ BlobStore.put(txt,list)
156
+ end
157
+ glCallList(BlobStore.get(txt))
158
+
159
+ glBindTexture(GL_TEXTURE_2D, 0)
160
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
161
+ glDisable(GL_BLEND)
162
+ glPopMatrix
163
+ end
164
+
165
+ end
@@ -0,0 +1,58 @@
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 HttpHelper
8
+
9
+ def self.parse_useragent(ua)
10
+ case ua
11
+ when /MSIE ([^;]+);/
12
+ "Internet Explorer #{$1}"
13
+ when /Firefox\/(\S+)/
14
+ "Firefox #{$1}"
15
+ when /Iceweasel\/(\S+)/
16
+ "Firefox #{$1}"
17
+ when /Camino\/(\S+)/
18
+ "Camino #{$1}"
19
+ when /Opera\/(\S+)/
20
+ "Opera #{$1}"
21
+ when /Safari\/([\d.]+)/
22
+ "Safari #{$1}"
23
+ when /Konqueror\/(\S+);/
24
+ "Konqueror #{$1}"
25
+ when /Wget/
26
+ 'Wget'
27
+
28
+ when /ia_archiver/
29
+ "Internet Archive Bot"
30
+ when /Googlebot/
31
+ "Google Bot"
32
+ when /msnbot-media/
33
+ "Microsoft Media Bot"
34
+ when /msnbot/
35
+ "Microsoft Bot"
36
+ when /Gigabot/
37
+ 'Gigabot'
38
+ when /Yahoo!/
39
+ 'Yahoo Bot'
40
+ when "-"
41
+ "-"
42
+ else
43
+ ua
44
+ end
45
+ end
46
+
47
+ def self.generalize_url(url)
48
+ case url
49
+ when /^(.*?)\/(\d+)$/
50
+ "#{$1}/:id"
51
+ when /^(.*?)\/[a-zA-Z0-9]{32}(.*?)$/
52
+ "#{$1}/:md5#{$2 if $2}"
53
+ else
54
+ url
55
+ end
56
+ end
57
+
58
+ end
@@ -0,0 +1,17 @@
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 Item
8
+ attr_accessor :message, :size, :color, :type
9
+
10
+ def initialize(message, size, color, type)
11
+ @message = message
12
+ @size = size
13
+ @color = color
14
+ @type = type
15
+ end
16
+
17
+ end
@@ -0,0 +1,46 @@
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
+ require 'gl_tail/http_helper'
8
+
9
+ class Parser
10
+ attr_reader :source
11
+
12
+ def initialize( source )
13
+ @source = source
14
+ end
15
+
16
+ # DEPRECATED?
17
+ def server
18
+ @source
19
+ end
20
+
21
+ def self::inherited( klass )
22
+ parser_name = klass.to_s.sub( /Parser$/, '' ).downcase.intern
23
+
24
+ @registry ||= {}
25
+ @registry[ parser_name ] = klass
26
+ end
27
+
28
+ def self::registry
29
+ return @registry
30
+ end
31
+
32
+ def parse( line )
33
+ raise NotImplementedError,
34
+ "Concrete parsers must implement parse()"
35
+ end
36
+
37
+ # dsl-ish helper methods so the parsers don't call server.add_* anymore. That
38
+ # seems magical now that server isn't be explicitly passed anymore.
39
+ def add_activity( opts = {} )
40
+ @source.add_activity( opts )
41
+ end
42
+
43
+ def add_event( opts = {} )
44
+ @source.add_event( opts )
45
+ end
46
+ end
@@ -0,0 +1,56 @@
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
+ # Parser which handles access_logs in combined format from Apache
8
+ class ApacheParser < Parser
9
+ def parse( line )
10
+ _, host, user, domain, date, url, status, size, referrer, useragent = /([\d\S.]+) (\S+) (\S+) \[([^\]]+)\] \"(.+?)\" (\d+) ([\S]+) \"([^\"]+)\" \"([^\"]+)\"/.match(line).to_a
11
+
12
+ unless host
13
+ _, host, user, domain, date, url, status, size = /([\d\S.]+) (\S+) (\S+) \[([^\]]+)\] \"(.+?)\" (\d+) ([\S]+)/.match(line).to_a
14
+ end
15
+
16
+ if host
17
+ _, referrer_host, referrer_url = /^http[s]?:\/\/([^\/]+)(\/.*)/.match(referrer).to_a if referrer
18
+ method, url, http_version = url.split(" ")
19
+ url = method if url.nil?
20
+ url, parameters = url.split('?')
21
+
22
+ referrer.gsub!(/http:\/\//,'') if referrer
23
+
24
+ add_activity(:block => 'sites', :name => server.name, :size => size.to_i) # Size of activity based on size of request
25
+ add_activity(:block => 'urls', :name => url)
26
+ add_activity(:block => 'users', :name => host, :size => size.to_i)
27
+ add_activity(:block => 'referrers', :name => referrer) unless (referrer.nil? || referrer_host.nil? || referrer_host.include?(server.name) || referrer_host.include?(server.host))
28
+ add_activity(:block => 'user agents', :name => HttpHelper.parse_useragent(useragent), :type => 3) unless useragent.nil?
29
+
30
+ if( url.include?('.gif') || url.include?('.jpg') || url.include?('.png') || url.include?('.ico'))
31
+ type = 'image'
32
+ elsif url.include?('.css')
33
+ type = 'css'
34
+ elsif url.include?('.js')
35
+ type = 'javascript'
36
+ elsif url.include?('.swf')
37
+ type = 'flash'
38
+ elsif( url.include?('.avi') || url.include?('.ogm') || url.include?('.flv') || url.include?('.mpg') )
39
+ type = 'movie'
40
+ elsif( url.include?('.mp3') || url.include?('.wav') || url.include?('.fla') || url.include?('.aac') || url.include?('.ogg'))
41
+ type = 'music'
42
+ else
43
+ type = 'page'
44
+ end
45
+ add_activity(:block => 'content', :name => type)
46
+ add_activity(:block => 'status', :name => status, :type => 3) # don't show a blob
47
+
48
+ add_activity(:block => 'warnings', :name => "#{status}: #{url}") if status.to_i > 400
49
+
50
+ # Events to pop up
51
+ add_event(:block => 'info', :name => "Logins", :message => "Login...", :update_stats => true, :color => [1.5, 1.0, 0.5, 1.0]) if method == "POST" && url.include?('login')
52
+ add_event(:block => 'info', :name => "Sales", :message => "$", :update_stats => true, :color => [1.5, 0.0, 0.0, 1.0]) if method == "POST" && url.include?('/checkout')
53
+ add_event(:block => 'info', :name => "Signups", :message => "New User...", :update_stats => true, :color => [1.0, 1.0, 1.0, 1.0]) if( method == "POST" && (url.include?('/signup') || url.include?('/users/create')))
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,47 @@
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
+ # Parser which handles Internet Information Server (IIS) logs
8
+ class IISParser < Parser
9
+ def parse( line )
10
+ _, date, time,serverip, url, referrer, port, size, host, useragent, status = /^([\d-]+) ([\d:]+) ([\d.]+) (.+? .+?) (\S+) (.+?) (\S+) ([\d.]+) (.+?) (\d+) (.*)$/.match(line).to_a
11
+
12
+ if host
13
+ _, referrer_host, referrer_url = /^http[s]?:\/\/([^\/]+)(\/.*)/.match(referrer).to_a if referrer
14
+ method, url, http_version = url.split(" ")
15
+ url, parameters = url.split('?')
16
+
17
+ add_activity(:block => 'sites', :name => server.name, :size => size.to_i) # Size of activity based on size of request
18
+ add_activity(:block => 'urls', :name => url)
19
+ add_activity(:block => 'users', :name => host, :size => size.to_i)
20
+ add_activity(:block => 'referrers', :name => referrer) unless (referrer_host.nil? || referrer_host.include?(server.name) || referrer_host.include?(server.host) || referrer == '-')
21
+ add_activity(:block => 'user agents', :name => useragent, :type => 3)
22
+
23
+ if( url.include?('.gif') || url.include?('.jpg') || url.include?('.png') || url.include?('.ico'))
24
+ type = 'image'
25
+ elsif url.include?('.css')
26
+ type = 'css'
27
+ elsif url.include?('.js')
28
+ type = 'javascript'
29
+ elsif url.include?('.swf')
30
+ type = 'flash'
31
+ elsif( url.include?('.avi') || url.include?('.ogm') || url.include?('.flv') || url.include?('.mpg') )
32
+ type = 'movie'
33
+ elsif( url.include?('.mp3') || url.include?('.wav') || url.include?('.fla') || url.include?('.aac') || url.include?('.ogg'))
34
+ type = 'music'
35
+ else
36
+ type = 'page'
37
+ end
38
+ add_activity(:block => 'content', :name => type)
39
+ add_activity(:block => 'status', :name => status, :type => 3) # don't show a blob
40
+
41
+ # Events to pop up
42
+ add_event(:block => 'info', :name => "Logins", :message => "Login...", :update_stats => true, :color => [1.5, 1.0, 0.5, 1.0]) if method == "POST" && url.include?('login')
43
+ add_event(:block => 'info', :name => "Sales", :message => "$", :update_stats => true, :color => [1.5, 0.0, 0.0, 1.0]) if method == "POST" && url.include?('/checkout')
44
+ add_event(:block => 'info', :name => "Signups", :message => "New User...", :update_stats => true, :color => [1.0, 1.0, 1.0, 1.0]) if( method == "POST" && (url.include?('/signup') || url.include?('/users/create')))
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,29 @@
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
+ # Parser which handles logs from MySQL
8
+ class MysqlParser < Parser
9
+ def parse( line )
10
+ # 071013 9:43:17 7 Query select * from users where username='test' limit 10
11
+
12
+ if line.include? " Query "
13
+ _, query = /^.* Query\s+(.+)$/.match(line).to_a
14
+
15
+ if query
16
+ add_activity(:block => 'sites', :name => server.name)
17
+ add_activity(:block => 'database', :name => query)
18
+ end
19
+
20
+ elsif line.include? " Connect "
21
+ # 8 Connect debian-sys-maint@localhost on
22
+ _, user = /^.* Connect\s+(.+) on\s+/.match(line).to_a
23
+ if user
24
+ add_activity(:block => 'logins', :name => "#{user}/mysql" )
25
+ end
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,46 @@
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
+ # Parser which handles nginx logs
8
+ class NginxParser < Parser
9
+ def parse( line )
10
+ _, remote_addr, remote_user, status, request, size, referrer, http_user_agent, http_x_forwarded_for = /^([^\s]+) - ([^\s]+) \[.*\] (\d+) \"(.+)\" (\d+) \"(.*)\" \"([^\"]*)\" \"(.*)\"/.match(line).to_a
11
+
12
+ if request
13
+ _, referrer_host, referrer_url = /^http[s]?:\/\/([^\/]+)(\/.*)/.match(referrer).to_a if referrer
14
+ method, full_url, _ = request.split(' ')
15
+ url, parameters = full_url.split('?')
16
+
17
+ add_activity(:block => 'sites', :name => server.name, :size => size.to_i)
18
+ add_activity(:block => 'urls', :name => url)
19
+ add_activity(:block => 'users', :name => remote_addr, :size => size.to_i)
20
+ add_activity(:block => 'referrers', :name => referrer) unless (referrer_host.nil? || referrer_host.include?(server.name) || referrer_host.include?(server.host) || referrer == '-')
21
+ add_activity(:block => 'user agents', :name => http_user_agent, :type => 3) unless http_user_agent.nil?
22
+
23
+ if( url.include?('.gif') || url.include?('.jpg') || url.include?('.png') || url.include?('.ico'))
24
+ type = 'image'
25
+ elsif url.include?('.css')
26
+ type = 'css'
27
+ elsif url.include?('.js')
28
+ type = 'javascript'
29
+ elsif url.include?('.swf')
30
+ type = 'flash'
31
+ elsif( url.include?('.avi') || url.include?('.ogm') || url.include?('.flv') || url.include?('.mpg') )
32
+ type = 'movie'
33
+ elsif( url.include?('.mp3') || url.include?('.wav') || url.include?('.fla') || url.include?('.aac') || url.include?('.ogg'))
34
+ type = 'music'
35
+ else
36
+ type = 'page'
37
+ end
38
+
39
+ add_activity(:block => 'content', :name => type)
40
+ add_activity(:block => 'status', :name => status, :type => 3)
41
+
42
+ add_event(:block => 'info', :name => "Logins", :message => "Login...", :update_stats => true, :color => [1.5, 1.0, 0.5, 1.0]) if method == "POST" && url.include?('/login')
43
+ add_event(:block => 'info', :name => "Registration", :message => "Register", :update_stats => true, :color => [1.5, 0.0, 0.0, 1.0]) if method == "POST" && url.include?('/register')
44
+ end
45
+ end
46
+ end