semantic_logger 2.0.0 → 2.1.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.
- checksums.yaml +7 -0
- data/Gemfile +1 -1
- data/README.md +162 -159
- data/Rakefile +6 -5
- data/lib/semantic_logger.rb +1 -3
- data/lib/semantic_logger/appender/file.rb +9 -9
- data/lib/semantic_logger/appender/wrapper.rb +6 -6
- data/lib/semantic_logger/base.rb +13 -16
- data/lib/semantic_logger/loggable.rb +55 -3
- data/lib/semantic_logger/logger.rb +17 -47
- data/lib/semantic_logger/semantic_logger.rb +135 -0
- data/lib/semantic_logger/version.rb +1 -1
- data/test/loggable_test.rb +5 -5
- data/test/logger_test.rb +14 -13
- metadata +22 -52
- data/Gemfile.lock +0 -33
- data/nbproject/private/config.properties +0 -0
- data/nbproject/private/private.properties +0 -1
- data/nbproject/private/private.xml +0 -4
- data/nbproject/private/rake-d.txt +0 -4
- data/nbproject/project.properties +0 -7
- data/nbproject/project.xml +0 -16
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4f813c09eacb56b09335612d00c499738d0ee84c
|
4
|
+
data.tar.gz: ad074b21691cac740d8c0c6272d4263f4c41421a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1211db34d7bc22f0f6c319b636a67decd6a23717568778b7f77413826b4940a3e1c699685e0890cb64c54e5e65a9d677a7923e54935a5203de76ef671a9cb0bd
|
7
|
+
data.tar.gz: d940844e714486e76be5e5e6b839c3ccaedc66566781b2b8a9d51c09eb4b077652e7b2db0bce1004a3b41098143d9cd263aa6eb16b64a968b1278ef1455fb4d9
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -9,7 +9,7 @@ Improved logging for Ruby
|
|
9
9
|
|
10
10
|
As of SemanticLogger V2.0 the Rails logging is no longer automatically replaced
|
11
11
|
when including SemanticLogger. Include the [rails_semantic_logger](http://github.com/ClarityServices/rails_semantic_logger)
|
12
|
-
to replace the Rails default logger with SemanticLogger
|
12
|
+
gem to replace the Rails default logger with SemanticLogger
|
13
13
|
|
14
14
|
### Overview
|
15
15
|
|
@@ -61,13 +61,6 @@ Drop-in Replacement
|
|
61
61
|
* Supports current common logging interface
|
62
62
|
* No changes to existing to code to use new logger ( other than replacing the logger )
|
63
63
|
|
64
|
-
Rails 2 & 3 Support
|
65
|
-
|
66
|
-
* Just include the semantic_logger gem into Rails and it will immediately
|
67
|
-
replace the existing loggers to improve performance and information
|
68
|
-
in the log files
|
69
|
-
* The Rails 3 Tagged logging feature is already available for Rails 2 by use Semantic Logger
|
70
|
-
|
71
64
|
Thread Aware
|
72
65
|
|
73
66
|
* Includes the process and thread id information in every log entry
|
@@ -172,7 +165,7 @@ similar text output.
|
|
172
165
|
This can be changed over time to:
|
173
166
|
|
174
167
|
```ruby
|
175
|
-
|
168
|
+
logger.info("Queried table",
|
176
169
|
:duration => duration,
|
177
170
|
:result => result,
|
178
171
|
:table => "users",
|
@@ -240,7 +233,7 @@ logger.debug { "A total of #{result.inject(0) {|sum, i| i+sum }} were processed"
|
|
240
233
|
|
241
234
|
### Exceptions
|
242
235
|
|
243
|
-
The Semantic Logger adds an
|
236
|
+
The Semantic Logger adds an optional parameter to the existing log methods so that
|
244
237
|
a corresponding Exception can be logged in a standard way
|
245
238
|
|
246
239
|
```ruby
|
@@ -350,7 +343,7 @@ loggers for Rails, ActiveRecord::Base, ActionController::Base, and ActiveResourc
|
|
350
343
|
with wrappers that set their Class name. For example in semantic_logger/railtie.rb:
|
351
344
|
|
352
345
|
```ruby
|
353
|
-
ActiveRecord::Base.logger = SemanticLogger
|
346
|
+
ActiveRecord::Base.logger = SemanticLogger[ActiveRecord]
|
354
347
|
```
|
355
348
|
|
356
349
|
By replacing their loggers we now get the class name in the text logging output:
|
@@ -382,29 +375,6 @@ This will result in the log output identifying the log entry as from the Externa
|
|
382
375
|
|
383
376
|
2012-08-30 15:37:29.474 I [48308:ScriptThreadProcess: script/rails] (5.2ms) ExternalSupplier -- Calling external interface
|
384
377
|
|
385
|
-
[SyncAttr](https://github.com/ClarityServices/sync_attr) is a gem that supports
|
386
|
-
lazy loading and thread-safe initialization of class attributes
|
387
|
-
|
388
|
-
Extract from a Rails log file after adding the semantic_logger gem:
|
389
|
-
|
390
|
-
```
|
391
|
-
2012-10-19 12:05:46.736 I [35940:JRubyWorker-10] Rails --
|
392
|
-
|
393
|
-
Started GET "/" for 127.0.0.1 at 2012-10-19 12:05:46 +0000
|
394
|
-
2012-10-19 12:05:47.318 I [35940:JRubyWorker-10] ActionController -- Processing by AdminController#index as HTML
|
395
|
-
2012-10-19 12:05:47.633 D [35940:JRubyWorker-10] ActiveRecord -- User Load (2.0ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
|
396
|
-
2012-10-19 12:05:49.833 D [35940:JRubyWorker-10] ActiveRecord -- Role Load (2.0ms) SELECT `roles`.* FROM `roles`
|
397
|
-
2012-10-19 12:05:49.868 D [35940:JRubyWorker-10] ActiveRecord -- Role Load (1.0ms) SELECT * FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE (`roles_users`.user_id = 1 )
|
398
|
-
2012-10-19 12:05:49.885 I [35940:JRubyWorker-10] ActionController -- Rendered menus/_control_system.html.erb (98.0ms)
|
399
|
-
2012-10-19 12:05:51.014 I [35940:JRubyWorker-10] ActionController -- Rendered layouts/_top_bar.html.erb (386.0ms)
|
400
|
-
2012-10-19 12:05:51.071 D [35940:JRubyWorker-10] ActiveRecord -- Announcement Load (20.0ms) SELECT `announcements`.* FROM `announcements` WHERE `announcements`.`active` = 1 ORDER BY created_at desc
|
401
|
-
2012-10-19 12:05:51.072 I [35940:JRubyWorker-10] ActionController -- Rendered layouts/_announcement.html.erb (26.0ms)
|
402
|
-
2012-10-19 12:05:51.083 I [35940:JRubyWorker-10] ActionController -- Rendered layouts/_flash.html.erb (4.0ms)
|
403
|
-
2012-10-19 12:05:51.109 I [35940:JRubyWorker-10] ActionController -- Rendered layouts/_footer.html.erb (16.0ms)
|
404
|
-
2012-10-19 12:05:51.109 I [35940:JRubyWorker-10] ActionController -- Rendered admin/index.html.erb within layouts/base (1329.0ms)
|
405
|
-
2012-10-19 12:05:51.113 I [35940:JRubyWorker-10] ActionController -- Completed 200 OK in 3795ms (Views: 1349.0ms | ActiveRecord: 88.0ms | Mongo: 0.0ms)
|
406
|
-
```
|
407
|
-
|
408
378
|
#### Tagged Logging
|
409
379
|
|
410
380
|
Semantic Logger allows any Ruby or Rails program to also include tagged logging.
|
@@ -439,76 +409,140 @@ logger.with_payload(:user => 'Jack', :zip_code => 12345) do
|
|
439
409
|
end
|
440
410
|
```
|
441
411
|
|
442
|
-
### Using SemanticLogger
|
412
|
+
### Using SemanticLogger
|
443
413
|
|
444
|
-
|
414
|
+
When using SemanticLogger inside of Rails all we need to do is include the
|
415
|
+
rails_semantic_logger gem and the default Rails logger will be replaced with
|
416
|
+
Semantic Logger.
|
445
417
|
|
418
|
+
In a stand-alone or non-rails environment we can easily log to a file called
|
419
|
+
'development.log' as follows:
|
446
420
|
```ruby
|
447
421
|
require 'semantic_logger'
|
422
|
+
SemanticLogger.add_appender('development.log')
|
448
423
|
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
# Add a file appender to log everything to a file
|
453
|
-
SemanticLogger::Logger.appenders << SemanticLogger::Appender::File.new('dev.log')
|
424
|
+
logger = SemanticLogger['Example']
|
425
|
+
logger.info "Hello World"
|
426
|
+
```
|
454
427
|
|
455
|
-
|
456
|
-
|
428
|
+
By default it will only log :info and above, to log everything to the log file:
|
429
|
+
```ruby
|
430
|
+
require 'semantic_logger'
|
431
|
+
SemanticLogger.default_level = :trace
|
432
|
+
SemanticLogger.add_appender('development.log')
|
457
433
|
|
458
|
-
logger = SemanticLogger
|
434
|
+
logger = SemanticLogger['Example']
|
459
435
|
logger.info "Hello World"
|
436
|
+
logger.trace "Low level trace information"
|
460
437
|
```
|
461
438
|
|
462
|
-
|
439
|
+
By supplying multiple appenders Semantic Logger can write to multiple destinations
|
440
|
+
at the same time. For example, log to a file and the screen:
|
441
|
+
```ruby
|
442
|
+
require 'semantic_logger'
|
443
|
+
SemanticLogger.default_level = :trace
|
444
|
+
SemanticLogger.add_appender('development.log')
|
445
|
+
SemanticLogger.add_appender(STDOUT)
|
463
446
|
|
464
|
-
|
465
|
-
|
466
|
-
|
447
|
+
logger = SemanticLogger['Example']
|
448
|
+
logger.info "Hello World"
|
449
|
+
logger.trace "Low level trace information"
|
450
|
+
```
|
467
451
|
|
468
|
-
|
452
|
+
To reduce the log level of logging to STDOUT to just :info and above, add the
|
453
|
+
log_level such as :info as the second parameter when adding the appender:
|
454
|
+
```ruby
|
455
|
+
require 'semantic_logger'
|
456
|
+
SemanticLogger.default_level = :trace
|
457
|
+
SemanticLogger.add_appender('development.log')
|
458
|
+
SemanticLogger.add_appender(STDOUT, :info)
|
469
459
|
|
470
|
-
|
460
|
+
logger = SemanticLogger['Example']
|
461
|
+
logger.info "Hello World"
|
462
|
+
logger.trace "Low level trace information"
|
463
|
+
```
|
471
464
|
|
465
|
+
To log :debug and above to a log file, :error and above to $stderr, and :info
|
466
|
+
and above to MongoDB:
|
472
467
|
```ruby
|
473
|
-
|
474
|
-
|
468
|
+
require 'semantic_logger'
|
469
|
+
require 'mongo'
|
475
470
|
|
476
|
-
|
471
|
+
SemanticLogger.default_level = :debug
|
472
|
+
SemanticLogger.add_appender('development.log')
|
473
|
+
SemanticLogger.add_appender($stderr, :error)
|
477
474
|
|
478
|
-
|
479
|
-
|
475
|
+
mongo_appender = SemanticLogger::Appender::MongoDB.new(
|
476
|
+
:db => Mongodb::Connection.new['production_logging'],
|
477
|
+
:collection_size => 25.gigabytes
|
478
|
+
)
|
479
|
+
SemanticLogger.add_appender(mongo_appender, :info)
|
480
|
+
|
481
|
+
logger = SemanticLogger['Example']
|
482
|
+
logger.info "Hello World"
|
483
|
+
logger.trace "Low level trace information"
|
484
|
+
logger.error "Oops an error occurred"
|
485
|
+
logger.info("Login time", :user => 'Mary', :duration => 230, :ip_address=>'192.168.0.1')
|
480
486
|
```
|
481
487
|
|
482
|
-
|
488
|
+
When starting out with Semantic Logger it can be useful to gain all the benefits
|
489
|
+
of Semantic Logger and still continue to log to an existing logger:
|
490
|
+
```ruby
|
491
|
+
require 'logger'
|
492
|
+
require 'semantic_logger'
|
483
493
|
|
484
|
-
|
494
|
+
# Built-in Ruby logger
|
495
|
+
log = Logger.new(STDOUT)
|
496
|
+
log.level = Logger::DEBUG
|
485
497
|
|
486
|
-
|
487
|
-
|
498
|
+
SemanticLogger.default_level = :debug
|
499
|
+
SemanticLogger.add_appender(log)
|
488
500
|
|
489
|
-
|
490
|
-
|
491
|
-
|
501
|
+
logger = SemanticLogger['Example']
|
502
|
+
logger.info "Hello World"
|
503
|
+
logger.debug("Login time", :user => 'Joe', :duration => 100, :ip_address=>'127.0.0.1')
|
504
|
+
```
|
492
505
|
|
506
|
+
It is recommended that every class or module have it's own logging instance.
|
507
|
+
This can be achieved by including SemanticLogger::Loggable:
|
493
508
|
```ruby
|
494
|
-
|
495
|
-
|
509
|
+
require 'semantic_logger'
|
510
|
+
SemanticLogger.default_level = :trace
|
511
|
+
SemanticLogger.add_appender('development.log')
|
512
|
+
|
513
|
+
class ExternalSupplier
|
514
|
+
# Makes available a class and instance level logger
|
515
|
+
# ExternalSupplier.logger and ExternalSupplier#logger
|
516
|
+
include SemanticLogger::Loggable
|
496
517
|
|
497
|
-
|
498
|
-
|
518
|
+
# logger class method example
|
519
|
+
def self.hostname=(hostname)
|
520
|
+
logger.debug "Setting hostname to #{hostname}"
|
521
|
+
@@hostname = hostname
|
522
|
+
end
|
499
523
|
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
)
|
524
|
+
# logger instance method example
|
525
|
+
def call_supplier(amount, name)
|
526
|
+
logger.debug "Calculating with amount", { :amount => amount, :name => name }
|
527
|
+
|
528
|
+
# Measure and log on completion how long the call took to the external supplier
|
529
|
+
logger.benchmark_info "Calling external interface" do
|
530
|
+
# Code to call the external supplier ...
|
531
|
+
end
|
532
|
+
end
|
510
533
|
end
|
511
534
|
```
|
535
|
+
|
536
|
+
### Configuration
|
537
|
+
|
538
|
+
The Semantic Logger follows the principle where multiple appenders can be active
|
539
|
+
at the same time. For example, this allows one to log to MongoDB and the Rails
|
540
|
+
log file at the same time.
|
541
|
+
|
542
|
+
#### Rails Configuration
|
543
|
+
|
544
|
+
To automatically replace the Rails logger with Semantic Logger use the gem [rails_semantic_logger](http://github.com/ClarityServices/rails_semantic_logger)
|
545
|
+
|
512
546
|
### Log Struct
|
513
547
|
|
514
548
|
Internally all log messages are passed around in a Log Struct. In order
|
@@ -565,16 +599,14 @@ Example: Formatter that just returns the Log Struct
|
|
565
599
|
```ruby
|
566
600
|
require 'semantic_logger'
|
567
601
|
|
568
|
-
SemanticLogger
|
602
|
+
SemanticLogger.default_level = :trace
|
569
603
|
|
570
|
-
|
604
|
+
SemanticLogger.add_appender(STDOUT) do |log|
|
571
605
|
# This formatter just returns the log struct as a string
|
572
606
|
log.inspect
|
573
607
|
end
|
574
608
|
|
575
|
-
|
576
|
-
|
577
|
-
logger = SemanticLogger::Logger.new('Hello')
|
609
|
+
logger = SemanticLogger['Hello']
|
578
610
|
logger.info "Hello World"
|
579
611
|
```
|
580
612
|
Output:
|
@@ -582,58 +614,56 @@ Output:
|
|
582
614
|
#<struct SemanticLogger::Base::Log level=:info, thread_name=70167090649820, name="Hello", message="Hello World", payload=nil, time=2012-10-24 10:09:33 -0400, duration=nil, tags=nil, level_index=2>
|
583
615
|
|
584
616
|
|
585
|
-
Example: Replace the
|
617
|
+
Example: Replace the default log file formatter
|
586
618
|
|
587
619
|
```ruby
|
588
|
-
|
589
|
-
|
590
|
-
config.semantic_logger.appenders.first.formatter = Proc.new do |log|
|
591
|
-
tags = log.tags.collect { |tag| "[#{tag}]" }.join(" ") + " " if log.tags && (log.tags.size > 0)
|
620
|
+
require 'semantic_logger'
|
621
|
+
SemanticLogger.default_level = :trace
|
592
622
|
|
593
|
-
|
594
|
-
|
595
|
-
message << " -- " << "#{log.exception.class}: #{log.exception.message}\n#{(log.exception.backtrace || []).join("\n")}" if log.exception
|
623
|
+
SemanticLogger.add_appender('development.log') do |log|
|
624
|
+
tags = log.tags.collect { |tag| "[#{tag}]" }.join(" ") + " " if log.tags && (log.tags.size > 0)
|
596
625
|
|
597
|
-
|
626
|
+
message = log.message.to_s
|
627
|
+
message << " -- " << log.payload.inspect if log.payload
|
628
|
+
message << " -- " << "#{log.exception.class}: #{log.exception.message}\n#{(log.exception.backtrace || []).join("\n")}" if log.exception
|
598
629
|
|
599
|
-
|
600
|
-
|
601
|
-
|
630
|
+
duration_str = log.duration ? "(#{'%.1f' % log.duration}ms) " : ''
|
631
|
+
|
632
|
+
"#{SemanticLogger::Appender::Base.formatted_time(log.time)} #{log.level.to_s[0..0].upcase} [#{$$}:#{log.thread_name}] #{tags}#{duration_str}#{log.name} -- #{message}"
|
633
|
+
end
|
602
634
|
```
|
603
635
|
|
604
|
-
Example: Replace the MongoDB formatter
|
636
|
+
Example: Replace the default MongoDB formatter
|
605
637
|
|
606
638
|
```ruby
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
config.semantic_logger.appenders << mongodb_appender
|
636
|
-
end
|
639
|
+
# Log to MongoDB and supply a custom document formatter
|
640
|
+
mongodb_appender = SemanticLogger::Appender::MongoDB.new(
|
641
|
+
:db => Cache::Work.db,
|
642
|
+
:collection_size => 25.gigabytes
|
643
|
+
) do |log|
|
644
|
+
# Return a document (Hash) of the data to be saved to MongoDB
|
645
|
+
document = {
|
646
|
+
:time => log.time,
|
647
|
+
:host_name => SemanticLogger::Appender::MongoDB.host_name,
|
648
|
+
:pid => $PID,
|
649
|
+
:thread_name => log.thread_name,
|
650
|
+
:name => log.name,
|
651
|
+
:level => log.level,
|
652
|
+
:level_index => log.level_index,
|
653
|
+
}
|
654
|
+
document[:application] = 'MyApplication'
|
655
|
+
document[:message] = SemanticLogger::Appender::MongoDB.strip_colorizing(log.message) if log.message
|
656
|
+
document[:duration] = log.duration if log.duration
|
657
|
+
document[:tags] = log.tags if log.tags && (log.tags.size > 0)
|
658
|
+
document[:payload] = log.payload if log.payload
|
659
|
+
document[:exception] = {
|
660
|
+
:name => log.exception.class.name,
|
661
|
+
:message => log.exception.message,
|
662
|
+
:stack_trace => log.exception.backtrace
|
663
|
+
} if log.exception
|
664
|
+
document
|
665
|
+
end
|
666
|
+
SemanticLogger.add_appender(mongodb_appender)
|
637
667
|
```
|
638
668
|
|
639
669
|
### SysLog and other standard loggers
|
@@ -692,14 +722,11 @@ In this way formatting and disk or network write delays will not affect the
|
|
692
722
|
performance of the application. Also adding more than one appender does not affect
|
693
723
|
the runtime performance of the application.
|
694
724
|
|
695
|
-
The
|
696
|
-
terminates it will
|
697
|
-
the program exits.
|
725
|
+
The logging thread is automatically started on initialization. When the program
|
726
|
+
terminates it will call flush on each of the appenders.
|
698
727
|
|
699
728
|
Calling SemanticLogger::Logger#flush will wait until all outstanding log messages
|
700
729
|
have been written and flushed to their respective appenders before returning.
|
701
|
-
Since all logging is now from this thread calling flush is no longer thread
|
702
|
-
specific.
|
703
730
|
|
704
731
|
### Write your own Appender
|
705
732
|
|
@@ -739,13 +766,13 @@ end
|
|
739
766
|
|
740
767
|
Sample program calling the above appender:
|
741
768
|
```ruby
|
742
|
-
SemanticLogger
|
769
|
+
SemanticLogger.default_level = :trace
|
743
770
|
# Log to file dev.log
|
744
|
-
SemanticLogger
|
771
|
+
SemanticLogger.add_appender('dev.log')
|
745
772
|
# Also log the above sample appender
|
746
|
-
SemanticLogger
|
773
|
+
SemanticLogger.add_appender(SimpleAppender.new)
|
747
774
|
|
748
|
-
logger = SemanticLogger
|
775
|
+
logger = SemanticLogger['Hello']
|
749
776
|
logger.info "Hello World"
|
750
777
|
```
|
751
778
|
|
@@ -775,36 +802,12 @@ To log to MongoDB, it also needs the Ruby Mongo Driver
|
|
775
802
|
- Configuration file to support adding appenders
|
776
803
|
- Based on end-user demand add appenders for: Syslog, hadoop, redis, etc..
|
777
804
|
|
778
|
-
Development
|
779
|
-
-----------
|
780
|
-
|
781
|
-
Want to contribute to Semantic Logger?
|
782
|
-
|
783
|
-
First clone the repo and run the tests:
|
784
|
-
|
785
|
-
git clone git://github.com/ClarityServices/semantic_logger.git
|
786
|
-
cd semantic_logger
|
787
|
-
rake test
|
788
|
-
|
789
|
-
Feel free to ping the mailing list with any issues and we'll try to resolve it.
|
790
|
-
|
791
|
-
Contributing
|
792
|
-
------------
|
793
|
-
|
794
|
-
Once you've made your great commits:
|
795
|
-
|
796
|
-
1. [Fork](http://help.github.com/forking/) semantic_logger
|
797
|
-
2. Create a topic branch - `git checkout -b my_branch`
|
798
|
-
3. Push to your branch - `git push origin my_branch`
|
799
|
-
4. Create an [Issue](http://github.com/ClarityServices/semantic_logger/issues) with a link to your branch
|
800
|
-
5. That's it!
|
801
|
-
|
802
805
|
Meta
|
803
806
|
----
|
804
807
|
|
805
808
|
* Code: `git clone git://github.com/ClarityServices/semantic_logger.git`
|
806
809
|
* Home: <https://github.com/ClarityServices/semantic_logger>
|
807
|
-
* Bugs: <http://github.com/
|
810
|
+
* Bugs: <http://github.com/ClarityServices/semantic_logger/issues>
|
808
811
|
* Gems: <http://rubygems.org/gems/semantic_logger>
|
809
812
|
|
810
813
|
This project uses [Semantic Versioning](http://semver.org/).
|
@@ -817,7 +820,7 @@ Reid Morrison :: reidmo@gmail.com :: @reidmorrison
|
|
817
820
|
License
|
818
821
|
-------
|
819
822
|
|
820
|
-
Copyright 2012 Clarity Services, Inc.
|
823
|
+
Copyright 2012,2013 Clarity Services, Inc.
|
821
824
|
|
822
825
|
Licensed under the Apache License, Version 2.0 (the "License");
|
823
826
|
you may not use this file except in compliance with the License.
|