lumber 0.10.2 → 0.11.0

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.
data/.travis.yml CHANGED
@@ -7,4 +7,7 @@ rvm:
7
7
  - jruby-19mode # JRuby in 1.9 mode
8
8
  # - rbx-18mode
9
9
  # - rbx-19mode
10
+ before_script:
11
+ - "export DISPLAY=:99.0"
12
+ - "sh -e /etc/init.d/xvfb start"
10
13
  script: bundle exec rspec spec
data/CHANGELOG CHANGED
@@ -1,3 +1,18 @@
1
+ 0.11.0 (05/22/2012)
2
+ -------------------
3
+
4
+ better initialization through rails mechanisms <29222cb>
5
+ fix docs, add monitor thread <d0381ab>
6
+ fix urls, typeahead, non-dev mode <47b9de6>
7
+ update copyright date <507a2b6>
8
+ update TODO <fa3e36c>
9
+ remove dead file <bb0476e>
10
+ tweak ui <8eaa8f9>
11
+ add ability to dynamically change logger levels, with webui to do so <6ebf9dd>
12
+ fix to allow overriding specific logger levels in yml <4a1e076>
13
+ Merge pull request #2 from backupify/rails_3.2 <534fa82>
14
+ since rails 3.2 has removed the class_inheritable_attribute call, we have to use the new class_attribute call to define loggers instead <3c6cd4a>
15
+
1
16
  0.9.6
2
17
  -----
3
18
 
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 Matt Conway
1
+ Copyright (c) 2009-2012 Matt Conway
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md ADDED
@@ -0,0 +1,65 @@
1
+ Lumber
2
+ ======
3
+
4
+ Lumber tries to make it easy to use the more robust [log4r](http://log4r.sourceforge.net/) logging system within your rails application.
5
+ To do this it sets up log4r configuration from a yml file, and provides utility methods for adding a
6
+ :logger accessor to classes dynamically as they get created. In the default setup shown below, calls
7
+ to logger from a model/controller/mailer, will include that classes name in the log output.
8
+
9
+ To use it in a rails project:
10
+
11
+ * add lumber to your Gemfile
12
+ * bundle install
13
+ * run the lumber generator, rails generate lumber, to get a basic config/log4r.yml
14
+ * enable lumber in your config/application.rb:
15
+
16
+
17
+ # To expose custom variables in log4r.yml
18
+ # config.lumber.some_option = "some_value
19
+ # you can set default_log_level here, config/environments/*.rb or in config/log4r.yml
20
+ # config.log_level = :debug
21
+ # enabling lumber sets config.logger to Log4r::Logger['rails']
22
+ config.lumber.enabled = true
23
+
24
+ You should be able to use lumber in a non-rails project too, but you will have to manually call Lumber.init - see the [docs](http://rubydoc.info/github/wr0ngway/lumber/Lumber#init-class_method) for details on parameters:
25
+
26
+ # before Rails::Initializer.run
27
+ #
28
+ require 'lumber'
29
+ Lumber.init(:root => "/my/project", :env => "development")
30
+
31
+ # Setup parent loggers for some known rails Base classes. Classes that inherit
32
+ # from these will have their logger as a parent so you can configure logging for
33
+ # subtrees of classes in log4r.yml
34
+ Lumber.setup_logger_hierarchy("ActiveRecord::Base", "rails::models")
35
+ Lumber.setup_logger_hierarchy("ActionController::Base", "rails::controllers")
36
+ Lumber.setup_logger_hierarchy("ActionMailer::Base", "rails::mailers")
37
+
38
+ # If you really want, you can make all classes have a logger
39
+ # Lumber.setup_logger_hierarchy("Object", "root::object")
40
+
41
+ Additionally, you can also add loggers to individual classes by including the LumberLoggerSupport module
42
+
43
+ class Foo
44
+ include Lumber::LoggerSupport
45
+ end
46
+
47
+ and Foo.logger/Foo.new.logger will log to a logger named "rails::Foo". This creates a heirarchy of loggers for classes
48
+ nested within modules, so you can use the namespace to enable/disable loggers
49
+
50
+ If you want to change the log level for a different environment, you can do so in log4r.yml or by using the standard rails "config.log_level" setting in config/environments/<env>.rb
51
+
52
+ # Set info as the default log level for production
53
+ config.log_level = :info
54
+
55
+ Lumber also comes with a Sinatra UI for dynamically overriding log levels at runtime. To use it, just run Lumber::Server as a rack application. The easiest way to do this is to map it to a route in your rails routes.rb (make sure you password protect it):
56
+
57
+ mount Lumber::Server, :at => "/lumber"
58
+
59
+ This will allow you to temporarily set lower log levels for specific loggers - e.g. if you want a specific model to have DEBUG logging for the next hour. For this to work, you need to activat
60
+
61
+
62
+ Copyright
63
+ ---------
64
+
65
+ Copyright (c) 2009-2012 Matt Conway. See LICENSE for details.
data/Rakefile CHANGED
@@ -14,61 +14,3 @@ Rake::RDocTask.new do |rdoc|
14
14
  rdoc.rdoc_files.include('README*')
15
15
  rdoc.rdoc_files.include('lib/**/*.rb')
16
16
  end
17
-
18
- task :changelog do
19
-
20
- changelog_file = 'CHANGELOG'
21
- entries = ""
22
-
23
- # Get a list of current tags
24
- tags = `git tag -l`.split
25
-
26
- # If we already have a changelog, make the last tag be the
27
- # last one in the changelog, and the next one be the one
28
- # following that in the tag list
29
- if File.exist?(changelog_file)
30
- entries = File.read(changelog_file)
31
- head = entries.split.first
32
- if head =~ /\d\.\d\.\d/
33
- last_tag = "v#{head}"
34
- idx = tags.index(last_tag)
35
- current_tag = tags[idx + 1]
36
- end
37
- end
38
-
39
- # Figure out last/current tags dn do some validation
40
- last_tag ||= tags[-2]
41
- current_tag ||= tags[-1]
42
-
43
- if last_tag.nil? && current_tag.nil?
44
- puts "Cannot generate a changelog without first tagging your repository"
45
- puts "Tags should be in the form vN.N.N"
46
- exit
47
- end
48
-
49
- if last_tag == current_tag
50
- puts "Nothing to do for equal revisions: #{last_tag}..#{current_tag}"
51
- exit
52
- end
53
-
54
-
55
- # Generate changelog from repo
56
- log=`git log --pretty='format:%s <%h> [%cn]' #{last_tag}..#{current_tag}`
57
-
58
- # Strip out maintenance entries
59
- log = log.lines.to_a.delete_if {|l| l =~ /^Regenerated gemspec/ || l =~ /^Version bump/ || l =~ /^Updated changelog/ }
60
-
61
- # Write out changelog file
62
- File.open(changelog_file, 'w') do |out|
63
- out.puts current_tag.gsub(/^v/, '')
64
- out.puts "-----"
65
- out.puts "\n"
66
- out.puts log
67
- out.puts "\n"
68
- out.puts entries
69
- end
70
-
71
- # Commit and push
72
- sh "git ci -m'Updated changelog' #{changelog_file}"
73
- sh "git push"
74
- end
data/TODO CHANGED
@@ -1,2 +1 @@
1
- * Add hook to allow tweaking log level for a running process
2
- * Add web app to access tweaking of log levels
1
+ * Allow Proc execution to predicate tweaking of log levels
data/lib/lumber.rb CHANGED
@@ -4,4 +4,11 @@ $:.unshift(File.dirname(__FILE__))
4
4
  require "lumber/lumber"
5
5
  require "lumber/logger_support"
6
6
  require "lumber/log4r"
7
+ require "lumber/level_util"
7
8
 
9
+
10
+ if defined?(Rails::Railtie)
11
+ module Lumber
12
+ require 'lumber/railtie'
13
+ end
14
+ end
@@ -0,0 +1,112 @@
1
+ module Lumber
2
+ module LevelUtil
3
+
4
+ extend MonitorMixin
5
+
6
+ LOG_LEVELS_KEY = "lumber:log_levels"
7
+
8
+ class MemoryCacheProvider
9
+ def initialize
10
+ @cache = {}
11
+ end
12
+
13
+ def read(key)
14
+ @cache[key]
15
+ end
16
+
17
+ def write(key, value, options={})
18
+ @cache[key] = value
19
+ end
20
+ end
21
+
22
+ # @return [MemoryCacheProvider] Where to persist the log level mappings (Rails.cache interface), defaults to Memory
23
+ attr_accessor :cache_provider
24
+ @cache_provider = MemoryCacheProvider.new
25
+
26
+ # @return [Integer] The time in seconds till the overrides expires, defaults to 3600
27
+ attr_accessor :ttl
28
+ @ttl = 3600
29
+
30
+ # Sets the logger level overrides into the cache_provider so that we can temporarily use
31
+ # a lower level for specific loggers to aid in debugging
32
+ #
33
+ # @param [Hash] Logger fullname mapping to level name, e.g. {'rails::models::User' => 'DEBUG'}
34
+ #
35
+ def set_levels(levels)
36
+ backup_levels(levels.keys)
37
+ @cache_provider.write(LOG_LEVELS_KEY, levels, :expire_in => @ttl)
38
+ end
39
+
40
+ def get_levels()
41
+ @cache_provider.read(LOG_LEVELS_KEY) || {}
42
+ end
43
+
44
+ # Activates previously set logger level overrides. Should be called
45
+ # at code entry points, e.g. an ApplicationController before_filter,
46
+ # or Resque::Worker callback
47
+ #
48
+ def activate_levels
49
+ levels = get_levels
50
+ if levels.size == 0
51
+ restore_levels
52
+ else
53
+ levels.each do |name, level|
54
+ logger = Lumber.find_or_create_logger(name)
55
+ level_val = Log4r::LNAMES.index(level)
56
+ logger.level = level_val if level_val
57
+ end
58
+ end
59
+ end
60
+
61
+ # Convenience method for starting a thread to watch for changes in log
62
+ # levels and apply them. You don't need to use this if you are manually
63
+ # calling activate levels at all your entry points.
64
+ #
65
+ # @param [Integer] How long to sleep between checks
66
+ # @return [Thread] The monitor thread
67
+ #
68
+ def start_monitor(interval=10)
69
+ Thread.new do
70
+ loop do
71
+ begin
72
+ activate_levels
73
+ rescue => e
74
+ $stderr.puts "Failure activating log levels: #{e}"
75
+ end
76
+ sleep interval
77
+ end
78
+ end
79
+ end
80
+
81
+ protected
82
+
83
+ @original_levels = {}
84
+
85
+ # Backs up original values of logger levels before we overwrite them
86
+ # This is better in local memory since we shouldn't reset loggers that we haven't set
87
+ # @param [Enumerable<String>] The logger names to backup
88
+ def backup_levels(loggers)
89
+ synchronize do
90
+ loggers.each do |name|
91
+ logger = Lumber.find_or_create_logger(name)
92
+ # only store the old level if we haven't overriden it's logger yet
93
+ @original_levels[name] ||= logger.level
94
+ end
95
+ end
96
+ end
97
+
98
+ # Restores original values of logger levels after expiration
99
+ def restore_levels
100
+ synchronize do
101
+ @original_levels.each do |name, level|
102
+ logger = Lumber.find_or_create_logger(name)
103
+ logger.level = level
104
+ end
105
+ @original_levels.clear
106
+ end
107
+ end
108
+
109
+ extend self
110
+
111
+ end
112
+ end
data/lib/lumber/lumber.rb CHANGED
@@ -34,6 +34,9 @@ module Lumber
34
34
  # * :env - defaults to RAILS_ENV if defined
35
35
  # * :config_file - defaults to <root>}/config/log4r.yml
36
36
  # * :log_file - defaults to <root>}/log/<env>.log
37
+ # * :monitor_enabled - defaults to true
38
+ # * :monitor_interval - defaults to 60
39
+ # * :monitor_store - defaults to Rails.cache if defined, memory otherwise, see Lumber::LevelUtil::MemoryCacheProvider for interface
37
40
  #
38
41
  # All config options get passed through to the log4r
39
42
  # configurator for use in defining outputters
@@ -43,11 +46,14 @@ module Lumber
43
46
  opts[:env] ||= RAILS_ENV if defined?(RAILS_ENV)
44
47
  opts[:config_file] ||= "#{opts[:root]}/config/log4r.yml"
45
48
  opts[:log_file] ||= "#{opts[:root]}/log/#{opts[:env]}.log"
49
+ opts[:monitor_enabled] ||= true
50
+ opts[:monitor_interval] ||= 60
51
+
46
52
  raise "Lumber.init missing one of :root, :env" unless opts[:root] && opts[:env]
47
53
 
48
54
  cfg = Log4r::YamlConfigurator
49
55
  opts.each do |k, v|
50
- cfg[k.to_s] = v
56
+ cfg[k.to_s] = v.to_s
51
57
  end
52
58
  cfg['hostname'] = Socket.gethostname
53
59
 
@@ -61,6 +67,13 @@ module Lumber
61
67
 
62
68
  @@registered_loggers = {}
63
69
  self.register_inheritance_handler()
70
+
71
+ if opts[:monitor_store]
72
+ LevelUtil.cache = opts[:monitor_store]
73
+ elsif defined?(RAILS_CACHE)
74
+ LevelUtil.cache = RAILS_CACHE
75
+ end
76
+ LevelUtil.start_monitor(opts[:monitor_interval]) if opts[:monitor_enabled]
64
77
  end
65
78
 
66
79
  def self.find_or_create_logger(fullname)
@@ -0,0 +1,38 @@
1
+ require 'rails'
2
+
3
+ module Lumber
4
+
5
+ class Railtie < Rails::Railtie
6
+
7
+ config.lumber = ActiveSupport::OrderedOptions.new
8
+
9
+ initializer "lumber.initialize_logger", :before => :initialize_logger do |app|
10
+ if app.config.lumber.enabled
11
+ opts = {:root => Rails.root.to_s, :env => Rails.env}.merge(app.config.lumber)
12
+ Lumber.init(opts)
13
+ unless opts[:disable_auto_loggers]
14
+ Lumber.setup_logger_hierarchy("ActiveRecord::Base", "rails::models")
15
+ Lumber.setup_logger_hierarchy("ActionController::Base", "rails::controllers")
16
+ Lumber.setup_logger_hierarchy("ActionMailer::Base", "rails::mailers")
17
+ end
18
+ config.logger = Log4r::Logger['rails']
19
+
20
+ config_level = app.config.log_level
21
+ if config_level
22
+ level_str = config_level.to_s.upcase
23
+ level = Log4r::LNAMES.index(level_str)
24
+ raise "Invalid log level: #{config_level}" unless level
25
+ Log4r::Logger['rails'].level = level
26
+ end
27
+ end
28
+ end
29
+
30
+ initializer "lumber.initialize_cache", :after => :initialize_cache do |app|
31
+ if app.config.lumber.enabled
32
+ LevelUtil.cache_provider = Rails.cache unless config.lumber.monitor_store
33
+ end
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,57 @@
1
+ require 'lumber'
2
+ require 'sinatra/base'
3
+ require 'erb'
4
+
5
+ module Lumber
6
+ class Server < Sinatra::Base
7
+
8
+ configure :development do
9
+ begin
10
+ require "sinatra/reloader"
11
+ register Sinatra::Reloader
12
+ rescue LoadError
13
+ end
14
+ end
15
+
16
+ set :root, "#{File.dirname(File.expand_path(__FILE__))}/server"
17
+
18
+ get "/" do
19
+ redirect url(:levels)
20
+ end
21
+
22
+ get "/levels" do
23
+ @levels = LevelUtil.get_levels
24
+ @ttl = LevelUtil.ttl
25
+ erb :levels
26
+ end
27
+
28
+ post "/levels" do
29
+ ttl = params['ttl']
30
+ logger_levels = Array(params['levels'])
31
+ levels = {}
32
+ logger_levels.each do |data|
33
+ name = data['name']
34
+ level = data['level'].strip
35
+ levels[name] = level
36
+ if ! Log4r::LNAMES.index(level)
37
+ @error = "Invalid log level: #{level}"
38
+ end
39
+ end
40
+
41
+ if @error
42
+ @levels = levels
43
+ @ttl = ttl
44
+ erb :levels
45
+ else
46
+ LevelUtil.set_levels(levels)
47
+ LevelUtil.ttl = ttl
48
+ redirect url(:levels)
49
+ end
50
+
51
+ end
52
+
53
+ # start the server if ruby file executed directly
54
+ run! if app_file == $0
55
+
56
+ end
57
+ end
@@ -0,0 +1,808 @@
1
+ /*!
2
+ * Bootstrap Responsive v2.0.3
3
+ *
4
+ * Copyright 2012 Twitter, Inc
5
+ * Licensed under the Apache License v2.0
6
+ * http://www.apache.org/licenses/LICENSE-2.0
7
+ *
8
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
9
+ */
10
+
11
+ .clearfix {
12
+ *zoom: 1;
13
+ }
14
+
15
+ .clearfix:before,
16
+ .clearfix:after {
17
+ display: table;
18
+ content: "";
19
+ }
20
+
21
+ .clearfix:after {
22
+ clear: both;
23
+ }
24
+
25
+ .hide-text {
26
+ font: 0/0 a;
27
+ color: transparent;
28
+ text-shadow: none;
29
+ background-color: transparent;
30
+ border: 0;
31
+ }
32
+
33
+ .input-block-level {
34
+ display: block;
35
+ width: 100%;
36
+ min-height: 28px;
37
+ -webkit-box-sizing: border-box;
38
+ -moz-box-sizing: border-box;
39
+ -ms-box-sizing: border-box;
40
+ box-sizing: border-box;
41
+ }
42
+
43
+ .hidden {
44
+ display: none;
45
+ visibility: hidden;
46
+ }
47
+
48
+ .visible-phone {
49
+ display: none !important;
50
+ }
51
+
52
+ .visible-tablet {
53
+ display: none !important;
54
+ }
55
+
56
+ .hidden-desktop {
57
+ display: none !important;
58
+ }
59
+
60
+ @media (max-width: 767px) {
61
+ .visible-phone {
62
+ display: inherit !important;
63
+ }
64
+ .hidden-phone {
65
+ display: none !important;
66
+ }
67
+ .hidden-desktop {
68
+ display: inherit !important;
69
+ }
70
+ .visible-desktop {
71
+ display: none !important;
72
+ }
73
+ }
74
+
75
+ @media (min-width: 768px) and (max-width: 979px) {
76
+ .visible-tablet {
77
+ display: inherit !important;
78
+ }
79
+ .hidden-tablet {
80
+ display: none !important;
81
+ }
82
+ .hidden-desktop {
83
+ display: inherit !important;
84
+ }
85
+ .visible-desktop {
86
+ display: none !important ;
87
+ }
88
+ }
89
+
90
+ @media (max-width: 480px) {
91
+ .nav-collapse {
92
+ -webkit-transform: translate3d(0, 0, 0);
93
+ }
94
+ .page-header h1 small {
95
+ display: block;
96
+ line-height: 18px;
97
+ }
98
+ input[type="checkbox"],
99
+ input[type="radio"] {
100
+ border: 1px solid #ccc;
101
+ }
102
+ .form-horizontal .control-group > label {
103
+ float: none;
104
+ width: auto;
105
+ padding-top: 0;
106
+ text-align: left;
107
+ }
108
+ .form-horizontal .controls {
109
+ margin-left: 0;
110
+ }
111
+ .form-horizontal .control-list {
112
+ padding-top: 0;
113
+ }
114
+ .form-horizontal .form-actions {
115
+ padding-right: 10px;
116
+ padding-left: 10px;
117
+ }
118
+ .modal {
119
+ position: absolute;
120
+ top: 10px;
121
+ right: 10px;
122
+ left: 10px;
123
+ width: auto;
124
+ margin: 0;
125
+ }
126
+ .modal.fade.in {
127
+ top: auto;
128
+ }
129
+ .modal-header .close {
130
+ padding: 10px;
131
+ margin: -10px;
132
+ }
133
+ .carousel-caption {
134
+ position: static;
135
+ }
136
+ }
137
+
138
+ @media (max-width: 767px) {
139
+ body {
140
+ padding-right: 20px;
141
+ padding-left: 20px;
142
+ }
143
+ .navbar-fixed-top,
144
+ .navbar-fixed-bottom {
145
+ margin-right: -20px;
146
+ margin-left: -20px;
147
+ }
148
+ .container-fluid {
149
+ padding: 0;
150
+ }
151
+ .dl-horizontal dt {
152
+ float: none;
153
+ width: auto;
154
+ clear: none;
155
+ text-align: left;
156
+ }
157
+ .dl-horizontal dd {
158
+ margin-left: 0;
159
+ }
160
+ .container {
161
+ width: auto;
162
+ }
163
+ .row-fluid {
164
+ width: 100%;
165
+ }
166
+ .row,
167
+ .thumbnails {
168
+ margin-left: 0;
169
+ }
170
+ [class*="span"],
171
+ .row-fluid [class*="span"] {
172
+ display: block;
173
+ float: none;
174
+ width: auto;
175
+ margin-left: 0;
176
+ }
177
+ .input-large,
178
+ .input-xlarge,
179
+ .input-xxlarge,
180
+ input[class*="span"],
181
+ select[class*="span"],
182
+ textarea[class*="span"],
183
+ .uneditable-input {
184
+ display: block;
185
+ width: 100%;
186
+ min-height: 28px;
187
+ -webkit-box-sizing: border-box;
188
+ -moz-box-sizing: border-box;
189
+ -ms-box-sizing: border-box;
190
+ box-sizing: border-box;
191
+ }
192
+ .input-prepend input,
193
+ .input-append input,
194
+ .input-prepend input[class*="span"],
195
+ .input-append input[class*="span"] {
196
+ display: inline-block;
197
+ width: auto;
198
+ }
199
+ }
200
+
201
+ @media (min-width: 768px) and (max-width: 979px) {
202
+ .row {
203
+ margin-left: -20px;
204
+ *zoom: 1;
205
+ }
206
+ .row:before,
207
+ .row:after {
208
+ display: table;
209
+ content: "";
210
+ }
211
+ .row:after {
212
+ clear: both;
213
+ }
214
+ [class*="span"] {
215
+ float: left;
216
+ margin-left: 20px;
217
+ }
218
+ .container,
219
+ .navbar-fixed-top .container,
220
+ .navbar-fixed-bottom .container {
221
+ width: 724px;
222
+ }
223
+ .span12 {
224
+ width: 724px;
225
+ }
226
+ .span11 {
227
+ width: 662px;
228
+ }
229
+ .span10 {
230
+ width: 600px;
231
+ }
232
+ .span9 {
233
+ width: 538px;
234
+ }
235
+ .span8 {
236
+ width: 476px;
237
+ }
238
+ .span7 {
239
+ width: 414px;
240
+ }
241
+ .span6 {
242
+ width: 352px;
243
+ }
244
+ .span5 {
245
+ width: 290px;
246
+ }
247
+ .span4 {
248
+ width: 228px;
249
+ }
250
+ .span3 {
251
+ width: 166px;
252
+ }
253
+ .span2 {
254
+ width: 104px;
255
+ }
256
+ .span1 {
257
+ width: 42px;
258
+ }
259
+ .offset12 {
260
+ margin-left: 764px;
261
+ }
262
+ .offset11 {
263
+ margin-left: 702px;
264
+ }
265
+ .offset10 {
266
+ margin-left: 640px;
267
+ }
268
+ .offset9 {
269
+ margin-left: 578px;
270
+ }
271
+ .offset8 {
272
+ margin-left: 516px;
273
+ }
274
+ .offset7 {
275
+ margin-left: 454px;
276
+ }
277
+ .offset6 {
278
+ margin-left: 392px;
279
+ }
280
+ .offset5 {
281
+ margin-left: 330px;
282
+ }
283
+ .offset4 {
284
+ margin-left: 268px;
285
+ }
286
+ .offset3 {
287
+ margin-left: 206px;
288
+ }
289
+ .offset2 {
290
+ margin-left: 144px;
291
+ }
292
+ .offset1 {
293
+ margin-left: 82px;
294
+ }
295
+ .row-fluid {
296
+ width: 100%;
297
+ *zoom: 1;
298
+ }
299
+ .row-fluid:before,
300
+ .row-fluid:after {
301
+ display: table;
302
+ content: "";
303
+ }
304
+ .row-fluid:after {
305
+ clear: both;
306
+ }
307
+ .row-fluid [class*="span"] {
308
+ display: block;
309
+ float: left;
310
+ width: 100%;
311
+ min-height: 28px;
312
+ margin-left: 2.762430939%;
313
+ *margin-left: 2.709239449638298%;
314
+ -webkit-box-sizing: border-box;
315
+ -moz-box-sizing: border-box;
316
+ -ms-box-sizing: border-box;
317
+ box-sizing: border-box;
318
+ }
319
+ .row-fluid [class*="span"]:first-child {
320
+ margin-left: 0;
321
+ }
322
+ .row-fluid .span12 {
323
+ width: 99.999999993%;
324
+ *width: 99.9468085036383%;
325
+ }
326
+ .row-fluid .span11 {
327
+ width: 91.436464082%;
328
+ *width: 91.38327259263829%;
329
+ }
330
+ .row-fluid .span10 {
331
+ width: 82.87292817100001%;
332
+ *width: 82.8197366816383%;
333
+ }
334
+ .row-fluid .span9 {
335
+ width: 74.30939226%;
336
+ *width: 74.25620077063829%;
337
+ }
338
+ .row-fluid .span8 {
339
+ width: 65.74585634900001%;
340
+ *width: 65.6926648596383%;
341
+ }
342
+ .row-fluid .span7 {
343
+ width: 57.182320438000005%;
344
+ *width: 57.129128948638304%;
345
+ }
346
+ .row-fluid .span6 {
347
+ width: 48.618784527%;
348
+ *width: 48.5655930376383%;
349
+ }
350
+ .row-fluid .span5 {
351
+ width: 40.055248616%;
352
+ *width: 40.0020571266383%;
353
+ }
354
+ .row-fluid .span4 {
355
+ width: 31.491712705%;
356
+ *width: 31.4385212156383%;
357
+ }
358
+ .row-fluid .span3 {
359
+ width: 22.928176794%;
360
+ *width: 22.874985304638297%;
361
+ }
362
+ .row-fluid .span2 {
363
+ width: 14.364640883%;
364
+ *width: 14.311449393638298%;
365
+ }
366
+ .row-fluid .span1 {
367
+ width: 5.801104972%;
368
+ *width: 5.747913482638298%;
369
+ }
370
+ input,
371
+ textarea,
372
+ .uneditable-input {
373
+ margin-left: 0;
374
+ }
375
+ input.span12,
376
+ textarea.span12,
377
+ .uneditable-input.span12 {
378
+ width: 714px;
379
+ }
380
+ input.span11,
381
+ textarea.span11,
382
+ .uneditable-input.span11 {
383
+ width: 652px;
384
+ }
385
+ input.span10,
386
+ textarea.span10,
387
+ .uneditable-input.span10 {
388
+ width: 590px;
389
+ }
390
+ input.span9,
391
+ textarea.span9,
392
+ .uneditable-input.span9 {
393
+ width: 528px;
394
+ }
395
+ input.span8,
396
+ textarea.span8,
397
+ .uneditable-input.span8 {
398
+ width: 466px;
399
+ }
400
+ input.span7,
401
+ textarea.span7,
402
+ .uneditable-input.span7 {
403
+ width: 404px;
404
+ }
405
+ input.span6,
406
+ textarea.span6,
407
+ .uneditable-input.span6 {
408
+ width: 342px;
409
+ }
410
+ input.span5,
411
+ textarea.span5,
412
+ .uneditable-input.span5 {
413
+ width: 280px;
414
+ }
415
+ input.span4,
416
+ textarea.span4,
417
+ .uneditable-input.span4 {
418
+ width: 218px;
419
+ }
420
+ input.span3,
421
+ textarea.span3,
422
+ .uneditable-input.span3 {
423
+ width: 156px;
424
+ }
425
+ input.span2,
426
+ textarea.span2,
427
+ .uneditable-input.span2 {
428
+ width: 94px;
429
+ }
430
+ input.span1,
431
+ textarea.span1,
432
+ .uneditable-input.span1 {
433
+ width: 32px;
434
+ }
435
+ }
436
+
437
+ @media (min-width: 1200px) {
438
+ .row {
439
+ margin-left: -30px;
440
+ *zoom: 1;
441
+ }
442
+ .row:before,
443
+ .row:after {
444
+ display: table;
445
+ content: "";
446
+ }
447
+ .row:after {
448
+ clear: both;
449
+ }
450
+ [class*="span"] {
451
+ float: left;
452
+ margin-left: 30px;
453
+ }
454
+ .container,
455
+ .navbar-fixed-top .container,
456
+ .navbar-fixed-bottom .container {
457
+ width: 1170px;
458
+ }
459
+ .span12 {
460
+ width: 1170px;
461
+ }
462
+ .span11 {
463
+ width: 1070px;
464
+ }
465
+ .span10 {
466
+ width: 970px;
467
+ }
468
+ .span9 {
469
+ width: 870px;
470
+ }
471
+ .span8 {
472
+ width: 770px;
473
+ }
474
+ .span7 {
475
+ width: 670px;
476
+ }
477
+ .span6 {
478
+ width: 570px;
479
+ }
480
+ .span5 {
481
+ width: 470px;
482
+ }
483
+ .span4 {
484
+ width: 370px;
485
+ }
486
+ .span3 {
487
+ width: 270px;
488
+ }
489
+ .span2 {
490
+ width: 170px;
491
+ }
492
+ .span1 {
493
+ width: 70px;
494
+ }
495
+ .offset12 {
496
+ margin-left: 1230px;
497
+ }
498
+ .offset11 {
499
+ margin-left: 1130px;
500
+ }
501
+ .offset10 {
502
+ margin-left: 1030px;
503
+ }
504
+ .offset9 {
505
+ margin-left: 930px;
506
+ }
507
+ .offset8 {
508
+ margin-left: 830px;
509
+ }
510
+ .offset7 {
511
+ margin-left: 730px;
512
+ }
513
+ .offset6 {
514
+ margin-left: 630px;
515
+ }
516
+ .offset5 {
517
+ margin-left: 530px;
518
+ }
519
+ .offset4 {
520
+ margin-left: 430px;
521
+ }
522
+ .offset3 {
523
+ margin-left: 330px;
524
+ }
525
+ .offset2 {
526
+ margin-left: 230px;
527
+ }
528
+ .offset1 {
529
+ margin-left: 130px;
530
+ }
531
+ .row-fluid {
532
+ width: 100%;
533
+ *zoom: 1;
534
+ }
535
+ .row-fluid:before,
536
+ .row-fluid:after {
537
+ display: table;
538
+ content: "";
539
+ }
540
+ .row-fluid:after {
541
+ clear: both;
542
+ }
543
+ .row-fluid [class*="span"] {
544
+ display: block;
545
+ float: left;
546
+ width: 100%;
547
+ min-height: 28px;
548
+ margin-left: 2.564102564%;
549
+ *margin-left: 2.510911074638298%;
550
+ -webkit-box-sizing: border-box;
551
+ -moz-box-sizing: border-box;
552
+ -ms-box-sizing: border-box;
553
+ box-sizing: border-box;
554
+ }
555
+ .row-fluid [class*="span"]:first-child {
556
+ margin-left: 0;
557
+ }
558
+ .row-fluid .span12 {
559
+ width: 100%;
560
+ *width: 99.94680851063829%;
561
+ }
562
+ .row-fluid .span11 {
563
+ width: 91.45299145300001%;
564
+ *width: 91.3997999636383%;
565
+ }
566
+ .row-fluid .span10 {
567
+ width: 82.905982906%;
568
+ *width: 82.8527914166383%;
569
+ }
570
+ .row-fluid .span9 {
571
+ width: 74.358974359%;
572
+ *width: 74.30578286963829%;
573
+ }
574
+ .row-fluid .span8 {
575
+ width: 65.81196581200001%;
576
+ *width: 65.7587743226383%;
577
+ }
578
+ .row-fluid .span7 {
579
+ width: 57.264957265%;
580
+ *width: 57.2117657756383%;
581
+ }
582
+ .row-fluid .span6 {
583
+ width: 48.717948718%;
584
+ *width: 48.6647572286383%;
585
+ }
586
+ .row-fluid .span5 {
587
+ width: 40.170940171000005%;
588
+ *width: 40.117748681638304%;
589
+ }
590
+ .row-fluid .span4 {
591
+ width: 31.623931624%;
592
+ *width: 31.5707401346383%;
593
+ }
594
+ .row-fluid .span3 {
595
+ width: 23.076923077%;
596
+ *width: 23.0237315876383%;
597
+ }
598
+ .row-fluid .span2 {
599
+ width: 14.529914530000001%;
600
+ *width: 14.4767230406383%;
601
+ }
602
+ .row-fluid .span1 {
603
+ width: 5.982905983%;
604
+ *width: 5.929714493638298%;
605
+ }
606
+ input,
607
+ textarea,
608
+ .uneditable-input {
609
+ margin-left: 0;
610
+ }
611
+ input.span12,
612
+ textarea.span12,
613
+ .uneditable-input.span12 {
614
+ width: 1160px;
615
+ }
616
+ input.span11,
617
+ textarea.span11,
618
+ .uneditable-input.span11 {
619
+ width: 1060px;
620
+ }
621
+ input.span10,
622
+ textarea.span10,
623
+ .uneditable-input.span10 {
624
+ width: 960px;
625
+ }
626
+ input.span9,
627
+ textarea.span9,
628
+ .uneditable-input.span9 {
629
+ width: 860px;
630
+ }
631
+ input.span8,
632
+ textarea.span8,
633
+ .uneditable-input.span8 {
634
+ width: 760px;
635
+ }
636
+ input.span7,
637
+ textarea.span7,
638
+ .uneditable-input.span7 {
639
+ width: 660px;
640
+ }
641
+ input.span6,
642
+ textarea.span6,
643
+ .uneditable-input.span6 {
644
+ width: 560px;
645
+ }
646
+ input.span5,
647
+ textarea.span5,
648
+ .uneditable-input.span5 {
649
+ width: 460px;
650
+ }
651
+ input.span4,
652
+ textarea.span4,
653
+ .uneditable-input.span4 {
654
+ width: 360px;
655
+ }
656
+ input.span3,
657
+ textarea.span3,
658
+ .uneditable-input.span3 {
659
+ width: 260px;
660
+ }
661
+ input.span2,
662
+ textarea.span2,
663
+ .uneditable-input.span2 {
664
+ width: 160px;
665
+ }
666
+ input.span1,
667
+ textarea.span1,
668
+ .uneditable-input.span1 {
669
+ width: 60px;
670
+ }
671
+ .thumbnails {
672
+ margin-left: -30px;
673
+ }
674
+ .thumbnails > li {
675
+ margin-left: 30px;
676
+ }
677
+ .row-fluid .thumbnails {
678
+ margin-left: 0;
679
+ }
680
+ }
681
+
682
+ @media (max-width: 979px) {
683
+ body {
684
+ padding-top: 0;
685
+ }
686
+ .navbar-fixed-top {
687
+ position: static;
688
+ margin-bottom: 18px;
689
+ }
690
+ .navbar-fixed-top .navbar-inner {
691
+ padding: 5px;
692
+ }
693
+ .navbar .container {
694
+ width: auto;
695
+ padding: 0;
696
+ }
697
+ .navbar .brand {
698
+ padding-right: 10px;
699
+ padding-left: 10px;
700
+ margin: 0 0 0 -5px;
701
+ }
702
+ .nav-collapse {
703
+ clear: both;
704
+ }
705
+ .nav-collapse .nav {
706
+ float: none;
707
+ margin: 0 0 9px;
708
+ }
709
+ .nav-collapse .nav > li {
710
+ float: none;
711
+ }
712
+ .nav-collapse .nav > li > a {
713
+ margin-bottom: 2px;
714
+ }
715
+ .nav-collapse .nav > .divider-vertical {
716
+ display: none;
717
+ }
718
+ .nav-collapse .nav .nav-header {
719
+ color: #999999;
720
+ text-shadow: none;
721
+ }
722
+ .nav-collapse .nav > li > a,
723
+ .nav-collapse .dropdown-menu a {
724
+ padding: 6px 15px;
725
+ font-weight: bold;
726
+ color: #999999;
727
+ -webkit-border-radius: 3px;
728
+ -moz-border-radius: 3px;
729
+ border-radius: 3px;
730
+ }
731
+ .nav-collapse .btn {
732
+ padding: 4px 10px 4px;
733
+ font-weight: normal;
734
+ -webkit-border-radius: 4px;
735
+ -moz-border-radius: 4px;
736
+ border-radius: 4px;
737
+ }
738
+ .nav-collapse .dropdown-menu li + li a {
739
+ margin-bottom: 2px;
740
+ }
741
+ .nav-collapse .nav > li > a:hover,
742
+ .nav-collapse .dropdown-menu a:hover {
743
+ background-color: #222222;
744
+ }
745
+ .nav-collapse.in .btn-group {
746
+ padding: 0;
747
+ margin-top: 5px;
748
+ }
749
+ .nav-collapse .dropdown-menu {
750
+ position: static;
751
+ top: auto;
752
+ left: auto;
753
+ display: block;
754
+ float: none;
755
+ max-width: none;
756
+ padding: 0;
757
+ margin: 0 15px;
758
+ background-color: transparent;
759
+ border: none;
760
+ -webkit-border-radius: 0;
761
+ -moz-border-radius: 0;
762
+ border-radius: 0;
763
+ -webkit-box-shadow: none;
764
+ -moz-box-shadow: none;
765
+ box-shadow: none;
766
+ }
767
+ .nav-collapse .dropdown-menu:before,
768
+ .nav-collapse .dropdown-menu:after {
769
+ display: none;
770
+ }
771
+ .nav-collapse .dropdown-menu .divider {
772
+ display: none;
773
+ }
774
+ .nav-collapse .navbar-form,
775
+ .nav-collapse .navbar-search {
776
+ float: none;
777
+ padding: 9px 15px;
778
+ margin: 9px 0;
779
+ border-top: 1px solid #222222;
780
+ border-bottom: 1px solid #222222;
781
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
782
+ -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
783
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
784
+ }
785
+ .navbar .nav-collapse .nav.pull-right {
786
+ float: none;
787
+ margin-left: 0;
788
+ }
789
+ .nav-collapse,
790
+ .nav-collapse.collapse {
791
+ height: 0;
792
+ overflow: hidden;
793
+ }
794
+ .navbar .btn-navbar {
795
+ display: block;
796
+ }
797
+ .navbar-static .navbar-inner {
798
+ padding-right: 10px;
799
+ padding-left: 10px;
800
+ }
801
+ }
802
+
803
+ @media (min-width: 980px) {
804
+ .nav-collapse.collapse {
805
+ height: auto !important;
806
+ overflow: visible !important;
807
+ }
808
+ }