semantic_logger 0.8.0 → 0.8.1
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/README.md +313 -9
- data/lib/semantic_logger/appender/mongodb.rb +1 -1
- data/lib/semantic_logger/logger.rb +3 -2
- data/lib/semantic_logger/version.rb +1 -1
- data/semantic_logger-0.8.0.gem +0 -0
- metadata +3 -3
data/README.md
CHANGED
|
@@ -1,14 +1,141 @@
|
|
|
1
1
|
semantic_logger
|
|
2
2
|
===============
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
logging with multiple appenders
|
|
4
|
+
Improved logging for Ruby
|
|
6
5
|
|
|
7
6
|
* http://github.com/ClarityServices/semantic_logger
|
|
8
7
|
|
|
8
|
+
### Overview
|
|
9
|
+
|
|
10
|
+
Semantic Logger takes logging in Ruby to a new level by adding several new
|
|
11
|
+
capabilities to the commonly used Logging API:
|
|
12
|
+
|
|
13
|
+
Dynamic
|
|
14
|
+
|
|
15
|
+
* Increase the log level at runtime for just one class
|
|
16
|
+
* For example enable debug level logging for a single class (logging instance)
|
|
17
|
+
while the program is running to get more detailed logging in production for just that class
|
|
18
|
+
|
|
19
|
+
Tagged Logging
|
|
20
|
+
|
|
21
|
+
* Supply custom data to be added to every log entry within a block of code,
|
|
22
|
+
including libraries and existing Gems
|
|
23
|
+
|
|
24
|
+
High Performance
|
|
25
|
+
|
|
26
|
+
* Logging is performed in a separate thread so as not to impact performance of
|
|
27
|
+
running code
|
|
28
|
+
|
|
29
|
+
Customizable
|
|
30
|
+
|
|
31
|
+
* Custom formatting by destination
|
|
32
|
+
* Easy to "roll your own" destination (Appender).
|
|
33
|
+
For example to log to Hadoop, Redis, etc..
|
|
34
|
+
|
|
35
|
+
Payload support
|
|
36
|
+
|
|
37
|
+
* Aside from the regular log message, a hash payload can also be supplied with
|
|
38
|
+
every log entry
|
|
39
|
+
* Very powerful when logging to NOSQL destinations that allow queries against
|
|
40
|
+
any data in the payload
|
|
41
|
+
|
|
42
|
+
Exceptions
|
|
43
|
+
|
|
44
|
+
* Directly log exceptions
|
|
45
|
+
* Semantic Logger standardizes the logging of exceptions with their backtraces
|
|
46
|
+
to text destinations and writes the exception elements as a hash to NOSQL
|
|
47
|
+
destinations
|
|
48
|
+
|
|
49
|
+
Drop-in Replacement
|
|
50
|
+
|
|
51
|
+
* Simple drop-in replacement for the Ruby, or the Rails loggers
|
|
52
|
+
* Supports current common logging interface
|
|
53
|
+
* No changes to existing to code to use new logger ( other than replacing the logger )
|
|
54
|
+
|
|
55
|
+
Rails 2 & 3 Support
|
|
56
|
+
|
|
57
|
+
* Just include the semantic_logger gem into Rails and it will immediately
|
|
58
|
+
replace the existing loggers to improve performance and information
|
|
59
|
+
in the log files
|
|
60
|
+
|
|
61
|
+
Thread Aware
|
|
62
|
+
|
|
63
|
+
* Includes the process and thread id information in every log entry
|
|
64
|
+
|
|
65
|
+
Trace Level
|
|
66
|
+
|
|
67
|
+
* :trace is a new level common in other languages and is commonly used for
|
|
68
|
+
logging trace level detail. It is intended for logging data at level below
|
|
69
|
+
:debug.
|
|
70
|
+
* :trace can be used for logging the actual data sent or received over the network
|
|
71
|
+
that is rarely needed but is critical when things are not working as expected.
|
|
72
|
+
* Since :trace can be enabled on a per class basis it can even be turned on
|
|
73
|
+
in production to resolve what was actually sent to an external vendor
|
|
74
|
+
|
|
75
|
+
Multiple Destinations
|
|
76
|
+
|
|
77
|
+
* Log to multiple destinations at the same time ( File and MongoDB, etc.. )
|
|
78
|
+
* Each destination can also have its own log level.
|
|
79
|
+
For example only write :info and above to MongoDB
|
|
80
|
+
Or have a second log file for :warn and above log entries
|
|
81
|
+
|
|
82
|
+
Benchmarking
|
|
83
|
+
|
|
84
|
+
* The performance of any block of code can be measured and logged at the same time
|
|
85
|
+
depending on the active log level
|
|
86
|
+
|
|
87
|
+
Semantic Capabilities
|
|
88
|
+
|
|
89
|
+
* With Semantic Logger it is simple to mix-in additional semantic information with
|
|
90
|
+
every log entry
|
|
91
|
+
* The application or class name is automatically included for every log entry under
|
|
92
|
+
a specific logging instance
|
|
93
|
+
* Includes the duration of blocks of code
|
|
94
|
+
* any Hash containing context specific information such as user_id or location information
|
|
95
|
+
|
|
96
|
+
Beyond Tagged Logging
|
|
97
|
+
|
|
98
|
+
* Supply entire hash of custom data to be added to the payload of every log entry
|
|
99
|
+
within a block of code, including libraries and existing Gems
|
|
100
|
+
|
|
101
|
+
NOSQL Destinations
|
|
102
|
+
|
|
103
|
+
* Every log entry is broken down into elements that NOSQL data stores can understand:
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"_id" : ObjectId("5034fa48e3f3fea945e83ef2"),
|
|
108
|
+
"time" : ISODate("2012-08-22T15:27:04.409Z"),
|
|
109
|
+
"host_name" : "release",
|
|
110
|
+
"pid" : 16112,
|
|
111
|
+
"thread_name" : "main",
|
|
112
|
+
"name" : "UserLocator",
|
|
113
|
+
"level" : "debug",
|
|
114
|
+
"message" : "Fetch user information",
|
|
115
|
+
"duration" : 12,
|
|
116
|
+
"payload" : {
|
|
117
|
+
"user" : "Jack",
|
|
118
|
+
"zip_code" : 12345,
|
|
119
|
+
"location" : "US"
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Thread Safe
|
|
125
|
+
|
|
126
|
+
* Semantic Logger is completely thread safe and all methods can be called
|
|
127
|
+
concurrently from any thread
|
|
128
|
+
* Tagged logging keeps any tagging data on a per-thread basis to ensure that
|
|
129
|
+
tags from different threads are not inter-mingled
|
|
130
|
+
|
|
9
131
|
### Introduction
|
|
10
132
|
|
|
11
133
|
SemanticLogger is a Logger that supports logging of meta-data, along with text messages
|
|
134
|
+
to multiple appenders
|
|
135
|
+
|
|
136
|
+
An appender is a Logging destination such as a File, MongoDB collection, etc..
|
|
137
|
+
Multiple Appenders can be active at the same time. All log entries are written
|
|
138
|
+
to each appender.
|
|
12
139
|
|
|
13
140
|
Machines can understand the logged data without having to use
|
|
14
141
|
complex Regular Expressions or other text parsing techniques
|
|
@@ -205,7 +332,7 @@ as debug calls only if the log level is set to trace
|
|
|
205
332
|
|
|
206
333
|
When Semantic Logger is included on a Rails project it automatically replaces the
|
|
207
334
|
loggers for Rails, ActiveRecord::Base, ActionController::Base, and ActiveResource::Base
|
|
208
|
-
with wrappers that set their Class name. For example in railtie.rb:
|
|
335
|
+
with wrappers that set their Class name. For example in semantic_logger/railtie.rb:
|
|
209
336
|
|
|
210
337
|
```ruby
|
|
211
338
|
ActiveRecord::Base.logger = SemanticLogger::Logger.new(ActiveRecord)
|
|
@@ -246,8 +373,37 @@ This will result in the log output identifying the log entry as from the Externa
|
|
|
246
373
|
[SyncAttr](https://github.com/ClarityServices/sync_attr) is a gem that supports
|
|
247
374
|
lazy loading and thread-safe initialization of class attributes
|
|
248
375
|
|
|
376
|
+
Extract from a Rails log file after adding the semantic_logger gem:
|
|
377
|
+
|
|
378
|
+
```
|
|
379
|
+
2012-10-19 12:05:46.736 I [35940:JRubyWorker-10] Rails --
|
|
380
|
+
|
|
381
|
+
Started GET "/" for 127.0.0.1 at 2012-10-19 12:05:46 +0000
|
|
382
|
+
2012-10-19 12:05:47.318 I [35940:JRubyWorker-10] ActionController -- Processing by AdminController#index as HTML
|
|
383
|
+
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
|
|
384
|
+
2012-10-19 12:05:49.833 D [35940:JRubyWorker-10] ActiveRecord -- Role Load (2.0ms) SELECT `roles`.* FROM `roles`
|
|
385
|
+
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 )
|
|
386
|
+
2012-10-19 12:05:49.885 I [35940:JRubyWorker-10] ActionController -- Rendered menus/_control_system.html.erb (98.0ms)
|
|
387
|
+
2012-10-19 12:05:51.014 I [35940:JRubyWorker-10] ActionController -- Rendered layouts/_top_bar.html.erb (386.0ms)
|
|
388
|
+
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
|
|
389
|
+
2012-10-19 12:05:51.072 I [35940:JRubyWorker-10] ActionController -- Rendered layouts/_announcement.html.erb (26.0ms)
|
|
390
|
+
2012-10-19 12:05:51.083 I [35940:JRubyWorker-10] ActionController -- Rendered layouts/_flash.html.erb (4.0ms)
|
|
391
|
+
2012-10-19 12:05:51.109 I [35940:JRubyWorker-10] ActionController -- Rendered layouts/_footer.html.erb (16.0ms)
|
|
392
|
+
2012-10-19 12:05:51.109 I [35940:JRubyWorker-10] ActionController -- Rendered admin/index.html.erb within layouts/base (1329.0ms)
|
|
393
|
+
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)
|
|
394
|
+
```
|
|
395
|
+
|
|
249
396
|
#### Tagged Logging
|
|
250
397
|
|
|
398
|
+
Semantic Logger allows any Ruby or Rails program to also include tagged logging.
|
|
399
|
+
|
|
400
|
+
This means that any logging performed within a block, including any called
|
|
401
|
+
libraries or gems to include the specified tag with every log entry.
|
|
402
|
+
|
|
403
|
+
Using Tagged logging is critical in any highly concurrent environment so that
|
|
404
|
+
one can quickly find all related log entries across all levels of code, and even
|
|
405
|
+
across threads
|
|
406
|
+
|
|
251
407
|
```ruby
|
|
252
408
|
logger.tagged(tracking_number) do
|
|
253
409
|
logger.debug("Hello World")
|
|
@@ -255,10 +411,17 @@ logger.tagged(tracking_number) do
|
|
|
255
411
|
end
|
|
256
412
|
```
|
|
257
413
|
|
|
258
|
-
####
|
|
414
|
+
#### Beyond Tagged Logging
|
|
415
|
+
|
|
416
|
+
Blocks of code can be tagged with not only values, but can be tagged with
|
|
417
|
+
entire hashes of data. The additional hash of data will be merged into
|
|
418
|
+
the payload of every log entry
|
|
419
|
+
|
|
420
|
+
For example every corresponding log entry could include a hash containing
|
|
421
|
+
a user_id, name, region, zip_code, tracking_number, etc...
|
|
259
422
|
|
|
260
423
|
```ruby
|
|
261
|
-
logger.with_payload(:user => 'Jack') do
|
|
424
|
+
logger.with_payload(:user => 'Jack', :zip_code => 12345) do
|
|
262
425
|
logger.debug("Hello World")
|
|
263
426
|
# ...
|
|
264
427
|
end
|
|
@@ -441,6 +604,52 @@ For example to replace the MongoDB formatter, in the environment configuration f
|
|
|
441
604
|
end
|
|
442
605
|
```
|
|
443
606
|
|
|
607
|
+
### SysLog and other standard loggers
|
|
608
|
+
|
|
609
|
+
To write log entries to a Syslog logger or any other logger of your choice,
|
|
610
|
+
that conforms the standard Ruby Logger API, Semantic Logger has an Appender to
|
|
611
|
+
use that logger.
|
|
612
|
+
|
|
613
|
+
For example to configure rails to also log to the Syslogger gem:
|
|
614
|
+
```ruby
|
|
615
|
+
config.after_initialize do
|
|
616
|
+
# Besides logging to the local file also log to Syslogger
|
|
617
|
+
config.semantic_logger.appenders << SemanticLogger::Appender::Wrapper.new(Syslogger.new("yourappname"))
|
|
618
|
+
end
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
### Performance
|
|
622
|
+
|
|
623
|
+
The traditional logging implementations write their log information to file in the
|
|
624
|
+
same thread of execution as the program itself. This means that for every log entry
|
|
625
|
+
the program has to wait for the data to be written.
|
|
626
|
+
|
|
627
|
+
With Semantic Logger it uses a dedicated thread for logging so that writing to
|
|
628
|
+
the log file or other appenders does not hold up program execution.
|
|
629
|
+
|
|
630
|
+
Also, since the logging is in this separate thread there is no impact to program
|
|
631
|
+
execution if we decided to add another appender.
|
|
632
|
+
For example, log to both a file and a MongoDB collection.
|
|
633
|
+
|
|
634
|
+
### Log Rotation
|
|
635
|
+
|
|
636
|
+
Since the log file is not re-opened with every call, when the log file needs
|
|
637
|
+
to be rotated, use a copy-truncate operation over deleting the file.
|
|
638
|
+
|
|
639
|
+
### Why Semantic logging?
|
|
640
|
+
|
|
641
|
+
Just as there is the initiative to add Semantic information to data on the web
|
|
642
|
+
so that computers can directly understand the content without having to resort
|
|
643
|
+
to complex regular expressions or machine learning techniques, it is important
|
|
644
|
+
to be able to do the same with log files or data.
|
|
645
|
+
|
|
646
|
+
Semantic Logger allows every log entry to have not only a message, but a payload
|
|
647
|
+
that can be written to a file or a NOSQL destination.
|
|
648
|
+
|
|
649
|
+
Once the logging data is in the NOSQL data store it can be queried quickly and
|
|
650
|
+
efficiently. Some SQL data stores also allow complex data types that could be used
|
|
651
|
+
for storing and querying the logging data
|
|
652
|
+
|
|
444
653
|
### Architecture & Performance
|
|
445
654
|
|
|
446
655
|
In order to ensure that logging does not hinder the performance of the application
|
|
@@ -449,7 +658,7 @@ for writing the log entries to each of the appenders.
|
|
|
449
658
|
|
|
450
659
|
In this way formatting and disk or network write delays will not affect the
|
|
451
660
|
performance of the application. Also adding more than one appender does not affect
|
|
452
|
-
the runtime performance of the application
|
|
661
|
+
the runtime performance of the application.
|
|
453
662
|
|
|
454
663
|
The additional thread is automatically started on initialization. When the program
|
|
455
664
|
terminates it will complete writing out all log data and flush the appenders before
|
|
@@ -460,9 +669,102 @@ have been written and flushed to their respective appenders before returning.
|
|
|
460
669
|
Since all logging is now from this thread calling flush is no longer thread
|
|
461
670
|
specific.
|
|
462
671
|
|
|
672
|
+
### Write your own Appender
|
|
673
|
+
|
|
674
|
+
To write your own appender it should meet the following requirements:
|
|
675
|
+
|
|
676
|
+
* Inherit from SemanticLogger::Base
|
|
677
|
+
* In the initializer connect to the resource being logged to
|
|
678
|
+
* Implement #log(log) which needs to write to the relevant resource
|
|
679
|
+
* Implement #flush if the resource can be flushed
|
|
680
|
+
* Write a test for the new appender
|
|
681
|
+
|
|
682
|
+
The #log method takes the log struct as a parameter which is defined as follows:
|
|
683
|
+
```ruby
|
|
684
|
+
Log = Struct.new(:level, :thread_name, :name, :message, :payload, :time, :duration, :tags, :level_index)
|
|
685
|
+
```
|
|
686
|
+
level
|
|
687
|
+
|
|
688
|
+
* Log level of the supplied log call
|
|
689
|
+
* :trace, :debug, :info, :warn, :error, :fatal
|
|
690
|
+
|
|
691
|
+
thread_name
|
|
692
|
+
|
|
693
|
+
* Name or id of the thread in which the logging call was called
|
|
694
|
+
|
|
695
|
+
name
|
|
696
|
+
|
|
697
|
+
* Class name supplied to the logging instance
|
|
698
|
+
|
|
699
|
+
message
|
|
700
|
+
|
|
701
|
+
* Text message to be logged
|
|
702
|
+
|
|
703
|
+
payload [Hash|Exception]
|
|
704
|
+
|
|
705
|
+
* Optional Hash or Ruby Exception object to be logged
|
|
706
|
+
|
|
707
|
+
time [Time]
|
|
708
|
+
|
|
709
|
+
* The time at which the log entry was created
|
|
710
|
+
|
|
711
|
+
duration [Float]
|
|
712
|
+
|
|
713
|
+
* The time taken in milli-seconds to complete a benchmark call
|
|
714
|
+
|
|
715
|
+
tags [Array<String>]
|
|
716
|
+
|
|
717
|
+
* Any tags active on the thread when the log call was made
|
|
718
|
+
|
|
719
|
+
level_index
|
|
720
|
+
|
|
721
|
+
* Internal use only. Index of the log level
|
|
722
|
+
|
|
723
|
+
Basic outline for an Appender:
|
|
724
|
+
|
|
725
|
+
```ruby
|
|
726
|
+
require 'semantic_logger'
|
|
727
|
+
|
|
728
|
+
class SimpleAppender < SemanticLogger::Base
|
|
729
|
+
def initialize(level=nil, &block)
|
|
730
|
+
# Set the log level and formatter if supplied
|
|
731
|
+
super(level, &block)
|
|
732
|
+
end
|
|
733
|
+
|
|
734
|
+
# Just display the log struct
|
|
735
|
+
def log(log)
|
|
736
|
+
p log
|
|
737
|
+
end
|
|
738
|
+
|
|
739
|
+
# Optional
|
|
740
|
+
def flush
|
|
741
|
+
puts "Flush :)"
|
|
742
|
+
end
|
|
743
|
+
end
|
|
744
|
+
```
|
|
745
|
+
|
|
746
|
+
Sample program calling the above appender:
|
|
747
|
+
```ruby
|
|
748
|
+
SemanticLogger::Logger.default_level = :trace
|
|
749
|
+
# Log to file dev.log
|
|
750
|
+
SemanticLogger::Logger.appenders << SemanticLogger::Appender::File.new('dev.log')
|
|
751
|
+
# Also log the above sample appender
|
|
752
|
+
SemanticLogger::Logger.appenders << SimpleAppender.new
|
|
753
|
+
|
|
754
|
+
logger = SemanticLogger::Logger.new('Hello')
|
|
755
|
+
logger.info "Hello World"
|
|
756
|
+
```
|
|
757
|
+
|
|
758
|
+
Look at the [existing appenders](https://github.com/ClarityServices/semantic_logger/tree/master/lib/semantic_logger/appender) for good examples
|
|
759
|
+
|
|
760
|
+
To have your appender included in the standard list of appenders follow the fork
|
|
761
|
+
instructions below.
|
|
762
|
+
Very Important: New appenders will not be accepted without complete working tests.
|
|
763
|
+
See the [MongoDB Appender Test](https://github.com/ClarityServices/semantic_logger/blob/master/test/appender_mongodb_test.rb) for an example.
|
|
764
|
+
|
|
463
765
|
### Dependencies
|
|
464
766
|
|
|
465
|
-
- Ruby MRI 1.8.7 (or above) Or, JRuby 1.6.3 (or above)
|
|
767
|
+
- Ruby MRI 1.8.7, 1.9.3 (or above) Or, JRuby 1.6.3 (or above)
|
|
466
768
|
- Optional: Rails 3.0.10 (or above)
|
|
467
769
|
- Optional: To log to MongoDB, Mongo Ruby Driver 1.5.2 or above
|
|
468
770
|
|
|
@@ -476,7 +778,9 @@ To log to MongoDB
|
|
|
476
778
|
|
|
477
779
|
### Future
|
|
478
780
|
|
|
479
|
-
-
|
|
781
|
+
- Configuration file to support setting the log level for a specific class
|
|
782
|
+
- Configuration file to support adding appenders
|
|
783
|
+
- Based on demand add direct appenders for: Syslog, hadoop, redis
|
|
480
784
|
|
|
481
785
|
Development
|
|
482
786
|
-----------
|
|
@@ -487,7 +791,7 @@ First clone the repo and run the tests:
|
|
|
487
791
|
|
|
488
792
|
git clone git://github.com/ClarityServices/semantic_logger.git
|
|
489
793
|
cd semantic_logger
|
|
490
|
-
|
|
794
|
+
rake test
|
|
491
795
|
|
|
492
796
|
Feel free to ping the mailing list with any issues and we'll try to resolve it.
|
|
493
797
|
|
|
@@ -49,6 +49,7 @@ module SemanticLogger
|
|
|
49
49
|
|
|
50
50
|
# Initial default Level for all new instances of SemanticLogger::Logger
|
|
51
51
|
@@default_level = :info
|
|
52
|
+
@@appender_thread = nil
|
|
52
53
|
|
|
53
54
|
# Allow for setting the global default log level
|
|
54
55
|
# This change only applies to _new_ loggers, existing logger levels
|
|
@@ -99,7 +100,7 @@ module SemanticLogger
|
|
|
99
100
|
# Flush all queued log entries disk, database, etc.
|
|
100
101
|
# All queued log messages are written and then each appender is flushed in turn
|
|
101
102
|
def self.flush
|
|
102
|
-
return false unless started?
|
|
103
|
+
return false unless started? && @@appender_thread && @@appender_thread.alive?
|
|
103
104
|
|
|
104
105
|
reply_queue = Queue.new
|
|
105
106
|
queue << { :command => :flush, :reply_queue => reply_queue }
|
|
@@ -172,7 +173,7 @@ module SemanticLogger
|
|
|
172
173
|
#
|
|
173
174
|
# Should any appender fail to log or flush, the exception is logged and
|
|
174
175
|
# other appenders will still be called
|
|
175
|
-
Thread.new do
|
|
176
|
+
@@appender_thread = Thread.new do
|
|
176
177
|
logger.debug "SemanticLogger::Logger Appender thread started"
|
|
177
178
|
begin
|
|
178
179
|
count = 0
|
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: semantic_logger
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.8.
|
|
4
|
+
version: 0.8.1
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2012-10-
|
|
12
|
+
date: 2012-10-19 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: sync_attr
|
|
@@ -111,7 +111,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
111
111
|
version: '0'
|
|
112
112
|
segments:
|
|
113
113
|
- 0
|
|
114
|
-
hash:
|
|
114
|
+
hash: -3615546680742578594
|
|
115
115
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
116
116
|
none: false
|
|
117
117
|
requirements:
|