lumber 0.10.2 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }