chronometer 0.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/Users/segiddins/Development/OpenSource/chronometer/CODE_OF_CONDUCT.md +74 -0
 - data/Users/segiddins/Development/OpenSource/chronometer/LICENSE.txt +21 -0
 - data/Users/segiddins/Development/OpenSource/chronometer/README.md +43 -0
 - data/Users/segiddins/Development/OpenSource/chronometer/exe/chronometer +6 -0
 - data/Users/segiddins/Development/OpenSource/chronometer/lib/chronometer.rb +130 -0
 - data/Users/segiddins/Development/OpenSource/chronometer/lib/chronometer/command.rb +73 -0
 - data/Users/segiddins/Development/OpenSource/chronometer/lib/chronometer/dsl.rb +47 -0
 - data/Users/segiddins/Development/OpenSource/chronometer/lib/chronometer/event.rb +17 -0
 - data/Users/segiddins/Development/OpenSource/chronometer/lib/chronometer/trace_event.rb +44 -0
 - data/Users/segiddins/Development/OpenSource/chronometer/lib/chronometer/version.rb +5 -0
 - data/exe/chronometer +6 -0
 - metadata +126 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA256:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 2f287e03bd1e18ecf333ec08905f25922656bd4ad1ac736276c7622d20ad9d4b
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: bc752a7b82c034920fea0bc94dca60ecc5682bd554f099103b7f100a9366bc23
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: b08dbe0747ea4edf7a504698354e8622ef45d625e7416f29350d6ccccb09f098e0fd4af6c8efac80af9f3e86c8e51c13616ef61d45b6e7703ed77aa09a20cc9f
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: c4eca04ceed0cf1593995655c609313cd3a8d2497a69e258a5cc69a1ad119565f68d3b1c6a230940f0339300430ae2eaaf6d2260cb4d79369534fe413ada43c0
         
     | 
| 
         @@ -0,0 +1,74 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Contributor Covenant Code of Conduct
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            ## Our Pledge
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            In the interest of fostering an open and welcoming environment, we as
         
     | 
| 
      
 6 
     | 
    
         
            +
            contributors and maintainers pledge to making participation in our project and
         
     | 
| 
      
 7 
     | 
    
         
            +
            our community a harassment-free experience for everyone, regardless of age, body
         
     | 
| 
      
 8 
     | 
    
         
            +
            size, disability, ethnicity, gender identity and expression, level of experience,
         
     | 
| 
      
 9 
     | 
    
         
            +
            nationality, personal appearance, race, religion, or sexual identity and
         
     | 
| 
      
 10 
     | 
    
         
            +
            orientation.
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            ## Our Standards
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            Examples of behavior that contributes to creating a positive environment
         
     | 
| 
      
 15 
     | 
    
         
            +
            include:
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            * Using welcoming and inclusive language
         
     | 
| 
      
 18 
     | 
    
         
            +
            * Being respectful of differing viewpoints and experiences
         
     | 
| 
      
 19 
     | 
    
         
            +
            * Gracefully accepting constructive criticism
         
     | 
| 
      
 20 
     | 
    
         
            +
            * Focusing on what is best for the community
         
     | 
| 
      
 21 
     | 
    
         
            +
            * Showing empathy towards other community members
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            Examples of unacceptable behavior by participants include:
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            * The use of sexualized language or imagery and unwelcome sexual attention or
         
     | 
| 
      
 26 
     | 
    
         
            +
            advances
         
     | 
| 
      
 27 
     | 
    
         
            +
            * Trolling, insulting/derogatory comments, and personal or political attacks
         
     | 
| 
      
 28 
     | 
    
         
            +
            * Public or private harassment
         
     | 
| 
      
 29 
     | 
    
         
            +
            * Publishing others' private information, such as a physical or electronic
         
     | 
| 
      
 30 
     | 
    
         
            +
              address, without explicit permission
         
     | 
| 
      
 31 
     | 
    
         
            +
            * Other conduct which could reasonably be considered inappropriate in a
         
     | 
| 
      
 32 
     | 
    
         
            +
              professional setting
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            ## Our Responsibilities
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            Project maintainers are responsible for clarifying the standards of acceptable
         
     | 
| 
      
 37 
     | 
    
         
            +
            behavior and are expected to take appropriate and fair corrective action in
         
     | 
| 
      
 38 
     | 
    
         
            +
            response to any instances of unacceptable behavior.
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            Project maintainers have the right and responsibility to remove, edit, or
         
     | 
| 
      
 41 
     | 
    
         
            +
            reject comments, commits, code, wiki edits, issues, and other contributions
         
     | 
| 
      
 42 
     | 
    
         
            +
            that are not aligned to this Code of Conduct, or to ban temporarily or
         
     | 
| 
      
 43 
     | 
    
         
            +
            permanently any contributor for other behaviors that they deem inappropriate,
         
     | 
| 
      
 44 
     | 
    
         
            +
            threatening, offensive, or harmful.
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            ## Scope
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
            This Code of Conduct applies both within project spaces and in public spaces
         
     | 
| 
      
 49 
     | 
    
         
            +
            when an individual is representing the project or its community. Examples of
         
     | 
| 
      
 50 
     | 
    
         
            +
            representing a project or community include using an official project e-mail
         
     | 
| 
      
 51 
     | 
    
         
            +
            address, posting via an official social media account, or acting as an appointed
         
     | 
| 
      
 52 
     | 
    
         
            +
            representative at an online or offline event. Representation of a project may be
         
     | 
| 
      
 53 
     | 
    
         
            +
            further defined and clarified by project maintainers.
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
            ## Enforcement
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
            Instances of abusive, harassing, or otherwise unacceptable behavior may be
         
     | 
| 
      
 58 
     | 
    
         
            +
            reported by contacting the project team at segiddins@squareup.com. All
         
     | 
| 
      
 59 
     | 
    
         
            +
            complaints will be reviewed and investigated and will result in a response that
         
     | 
| 
      
 60 
     | 
    
         
            +
            is deemed necessary and appropriate to the circumstances. The project team is
         
     | 
| 
      
 61 
     | 
    
         
            +
            obligated to maintain confidentiality with regard to the reporter of an incident.
         
     | 
| 
      
 62 
     | 
    
         
            +
            Further details of specific enforcement policies may be posted separately.
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
            Project maintainers who do not follow or enforce the Code of Conduct in good
         
     | 
| 
      
 65 
     | 
    
         
            +
            faith may face temporary or permanent repercussions as determined by other
         
     | 
| 
      
 66 
     | 
    
         
            +
            members of the project's leadership.
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
            ## Attribution
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
            This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
         
     | 
| 
      
 71 
     | 
    
         
            +
            available at [http://contributor-covenant.org/version/1/4][version]
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
            [homepage]: http://contributor-covenant.org
         
     | 
| 
      
 74 
     | 
    
         
            +
            [version]: http://contributor-covenant.org/version/1/4/
         
     | 
| 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            The MIT License (MIT)
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Copyright (c) 2018 Samuel Giddins
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining a copy
         
     | 
| 
      
 6 
     | 
    
         
            +
            of this software and associated documentation files (the "Software"), to deal
         
     | 
| 
      
 7 
     | 
    
         
            +
            in the Software without restriction, including without limitation the rights
         
     | 
| 
      
 8 
     | 
    
         
            +
            to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
         
     | 
| 
      
 9 
     | 
    
         
            +
            copies of the Software, and to permit persons to whom the Software is
         
     | 
| 
      
 10 
     | 
    
         
            +
            furnished to do so, subject to the following conditions:
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be included in
         
     | 
| 
      
 13 
     | 
    
         
            +
            all copies or substantial portions of the Software.
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         
     | 
| 
      
 16 
     | 
    
         
            +
            IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         
     | 
| 
      
 17 
     | 
    
         
            +
            FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
         
     | 
| 
      
 18 
     | 
    
         
            +
            AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         
     | 
| 
      
 19 
     | 
    
         
            +
            LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         
     | 
| 
      
 20 
     | 
    
         
            +
            OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
         
     | 
| 
      
 21 
     | 
    
         
            +
            THE SOFTWARE.
         
     | 
| 
         @@ -0,0 +1,43 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Chronometer
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            A small gem that generates Chrome trace files for Ruby programs.
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            ## Installation
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            Add this line to your application's Gemfile:
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 10 
     | 
    
         
            +
            gem 'chronometer'
         
     | 
| 
      
 11 
     | 
    
         
            +
            ```
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            And then execute:
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                $ bundle
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            Or install it yourself as:
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                $ gem install chronometer
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            ## Usage
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            ```
         
     | 
| 
      
 24 
     | 
    
         
            +
            $ chronometer CocoaPods.chronofile -- pod --version
         
     | 
| 
      
 25 
     | 
    
         
            +
            ```
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            ## Development
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            ## Contributing
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/chronometer. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
            ## License
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
            The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
            ## Code of Conduct
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
            Everyone interacting in the Chronometer project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/chronometer/blob/master/CODE_OF_CONDUCT.md).
         
     | 
| 
         @@ -0,0 +1,130 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require_relative 'chronometer/dsl'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require_relative 'chronometer/event'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require_relative 'chronometer/trace_event'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require_relative 'chronometer/version'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            class Chronometer
         
     | 
| 
      
 9 
     | 
    
         
            +
              attr_reader :trace_events
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              def self.from_file(path, contents: File.read(path))
         
     | 
| 
      
 12 
     | 
    
         
            +
                new do
         
     | 
| 
      
 13 
     | 
    
         
            +
                  instance_eval(contents, path)
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              def initialize(&blk)
         
     | 
| 
      
 18 
     | 
    
         
            +
                dsl = DSL.new
         
     | 
| 
      
 19 
     | 
    
         
            +
                dsl.instance_exec(&blk)
         
     | 
| 
      
 20 
     | 
    
         
            +
                @events = dsl.events
         
     | 
| 
      
 21 
     | 
    
         
            +
                @tracepoints = dsl.tracepoints
         
     | 
| 
      
 22 
     | 
    
         
            +
                @trace_event_queue = Queue.new
         
     | 
| 
      
 23 
     | 
    
         
            +
                @trace_events = []
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              def install!
         
     | 
| 
      
 27 
     | 
    
         
            +
                @events.each { |e| install_method_hook(e) }
         
     | 
| 
      
 28 
     | 
    
         
            +
                @tracepoints.each { |tp| install_tracepoint(tp) }
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              def drain!
         
     | 
| 
      
 32 
     | 
    
         
            +
                loop { @trace_events << @trace_event_queue.pop(true) }
         
     | 
| 
      
 33 
     | 
    
         
            +
              rescue ThreadError
         
     | 
| 
      
 34 
     | 
    
         
            +
                nil
         
     | 
| 
      
 35 
     | 
    
         
            +
              end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
              def print_trace_event_report(dest, metadata: {})
         
     | 
| 
      
 38 
     | 
    
         
            +
                raise ArgumentError, 'cannot manually specify :traceEvents' if metadata.key?(:traceEvents)
         
     | 
| 
      
 39 
     | 
    
         
            +
                require 'json'
         
     | 
| 
      
 40 
     | 
    
         
            +
                File.open(dest, 'w') do |f|
         
     | 
| 
      
 41 
     | 
    
         
            +
                  f << JSON.generate(metadata)
         
     | 
| 
      
 42 
     | 
    
         
            +
                  f.seek(-1, :CUR) # remove closing }
         
     | 
| 
      
 43 
     | 
    
         
            +
                  f << ',' unless metadata.empty?
         
     | 
| 
      
 44 
     | 
    
         
            +
                  f << '"traceEvents":['
         
     | 
| 
      
 45 
     | 
    
         
            +
                  @trace_events.each_with_index do |te, i|
         
     | 
| 
      
 46 
     | 
    
         
            +
                    f << ',' unless i == 0
         
     | 
| 
      
 47 
     | 
    
         
            +
                    f << JSON.generate(te.to_h)
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
                  f << ']}'
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
              end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
              def self.timestamp_us
         
     | 
| 
      
 54 
     | 
    
         
            +
                Time.now.utc.to_f.*(1_000_000).round
         
     | 
| 
      
 55 
     | 
    
         
            +
              end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
              def register_trace_event(event)
         
     | 
| 
      
 58 
     | 
    
         
            +
                @trace_event_queue << event
         
     | 
| 
      
 59 
     | 
    
         
            +
              end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
              private
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
              def install_method_hook(event)
         
     | 
| 
      
 64 
     | 
    
         
            +
                cls = event.cls
         
     | 
| 
      
 65 
     | 
    
         
            +
                method = event.method
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                unbound_method = cls.instance_method(method)
         
     | 
| 
      
 68 
     | 
    
         
            +
                arg_labels = unbound_method.parameters.map(&:last)
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                timer = self
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                cls.send(:define_method, method) do |*args, &blk|
         
     | 
| 
      
 73 
     | 
    
         
            +
                  context = event.context&.call(self)
         
     | 
| 
      
 74 
     | 
    
         
            +
                  args_dict = arg_labels.zip(args).to_h
         
     | 
| 
      
 75 
     | 
    
         
            +
                  args_dict[:context] = context if context
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                  start_time = ::Chronometer.timestamp_us
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                  event_type = event.event_type
         
     | 
| 
      
 80 
     | 
    
         
            +
                  if event_type == :X
         
     | 
| 
      
 81 
     | 
    
         
            +
                    timer.register_trace_event TraceEvent.new(
         
     | 
| 
      
 82 
     | 
    
         
            +
                      process_id: Process.pid,
         
     | 
| 
      
 83 
     | 
    
         
            +
                      thread_id: Thread.current.object_id,
         
     | 
| 
      
 84 
     | 
    
         
            +
                      start_time_usec: ::Chronometer.timestamp_us,
         
     | 
| 
      
 85 
     | 
    
         
            +
                      event_type: :B,
         
     | 
| 
      
 86 
     | 
    
         
            +
                      name: event.name
         
     | 
| 
      
 87 
     | 
    
         
            +
                    )
         
     | 
| 
      
 88 
     | 
    
         
            +
                    event_type = :E
         
     | 
| 
      
 89 
     | 
    
         
            +
                  end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                  r0 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
         
     | 
| 
      
 92 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 93 
     | 
    
         
            +
                    unbound_method.bind(self).call(*args, &blk)
         
     | 
| 
      
 94 
     | 
    
         
            +
                  ensure
         
     | 
| 
      
 95 
     | 
    
         
            +
                    duration = Process.clock_gettime(Process::CLOCK_MONOTONIC).-(r0).*(1_000_000).round
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                    timer.register_trace_event TraceEvent.new(
         
     | 
| 
      
 98 
     | 
    
         
            +
                      process_id: Process.pid,
         
     | 
| 
      
 99 
     | 
    
         
            +
                      thread_id: Thread.current.object_id,
         
     | 
| 
      
 100 
     | 
    
         
            +
                      start_time_usec: event_type == :E ? ::Chronometer.timestamp_us : start_time,
         
     | 
| 
      
 101 
     | 
    
         
            +
                      event_type: event_type,
         
     | 
| 
      
 102 
     | 
    
         
            +
                      name: event.name,
         
     | 
| 
      
 103 
     | 
    
         
            +
                      args: args_dict,
         
     | 
| 
      
 104 
     | 
    
         
            +
                      category: event.category,
         
     | 
| 
      
 105 
     | 
    
         
            +
                      duration: duration,
         
     | 
| 
      
 106 
     | 
    
         
            +
                      cls: cls,
         
     | 
| 
      
 107 
     | 
    
         
            +
                      method: method
         
     | 
| 
      
 108 
     | 
    
         
            +
                    )
         
     | 
| 
      
 109 
     | 
    
         
            +
                  end
         
     | 
| 
      
 110 
     | 
    
         
            +
                end
         
     | 
| 
      
 111 
     | 
    
         
            +
              end
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
              def install_tracepoint(tracepoint)
         
     | 
| 
      
 114 
     | 
    
         
            +
                event_name, blk = tracepoint
         
     | 
| 
      
 115 
     | 
    
         
            +
                TracePoint.trace(event_name) do |tp|
         
     | 
| 
      
 116 
     | 
    
         
            +
                  next if tp.path == __FILE__
         
     | 
| 
      
 117 
     | 
    
         
            +
                  args = {
         
     | 
| 
      
 118 
     | 
    
         
            +
                    process_id: Process.pid,
         
     | 
| 
      
 119 
     | 
    
         
            +
                    thread_id: Thread.current.object_id,
         
     | 
| 
      
 120 
     | 
    
         
            +
                    start_time_usec: ::Chronometer.timestamp_us,
         
     | 
| 
      
 121 
     | 
    
         
            +
                    event_type: :I,
         
     | 
| 
      
 122 
     | 
    
         
            +
                    name: event_name
         
     | 
| 
      
 123 
     | 
    
         
            +
                  }
         
     | 
| 
      
 124 
     | 
    
         
            +
                  args.update blk&.call(tp)
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                  te = TraceEvent.new(**args)
         
     | 
| 
      
 127 
     | 
    
         
            +
                  register_trace_event(te)
         
     | 
| 
      
 128 
     | 
    
         
            +
                end
         
     | 
| 
      
 129 
     | 
    
         
            +
              end
         
     | 
| 
      
 130 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,73 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'claide'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'chronometer'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            class Chronometer
         
     | 
| 
      
 7 
     | 
    
         
            +
              module Command; end
         
     | 
| 
      
 8 
     | 
    
         
            +
              class Command::Chronometer < CLAide::Command
         
     | 
| 
      
 9 
     | 
    
         
            +
                self.version = VERSION
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                self.summary = "Trace a ruby program's execution using a chronofile"
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                self.arguments = [
         
     | 
| 
      
 14 
     | 
    
         
            +
                  CLAide::Argument.new('CHRONOFILE', true),
         
     | 
| 
      
 15 
     | 
    
         
            +
                  CLAide::Argument.new('RUBY_FILE', true),
         
     | 
| 
      
 16 
     | 
    
         
            +
                  CLAide::Argument.new('ARGUMENTS', false, true)
         
     | 
| 
      
 17 
     | 
    
         
            +
                ]
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                def self.options
         
     | 
| 
      
 20 
     | 
    
         
            +
                  [
         
     | 
| 
      
 21 
     | 
    
         
            +
                    ['--output=TRACE', 'The path to the tracefile chronometer will write']
         
     | 
| 
      
 22 
     | 
    
         
            +
                  ].concat(super)
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                def initialize(argv)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @chronofile = argv.shift_argument
         
     | 
| 
      
 27 
     | 
    
         
            +
                  @output = argv.option('output', "#{@chronofile}.trace")
         
     | 
| 
      
 28 
     | 
    
         
            +
                  @file_to_load = argv.shift_argument
         
     | 
| 
      
 29 
     | 
    
         
            +
                  @arguments = argv.remainder! if @chronofile && @file_to_load
         
     | 
| 
      
 30 
     | 
    
         
            +
                  super
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                def validate!
         
     | 
| 
      
 34 
     | 
    
         
            +
                  super
         
     | 
| 
      
 35 
     | 
    
         
            +
                  help! 'Must supply a chronofile' unless @chronofile
         
     | 
| 
      
 36 
     | 
    
         
            +
                  @chronofile_contents = begin
         
     | 
| 
      
 37 
     | 
    
         
            +
                                           File.read(@chronofile)
         
     | 
| 
      
 38 
     | 
    
         
            +
                                         rescue StandardError
         
     | 
| 
      
 39 
     | 
    
         
            +
                                           help!("No such chronofile `#{@chronofile}`")
         
     | 
| 
      
 40 
     | 
    
         
            +
                                         end
         
     | 
| 
      
 41 
     | 
    
         
            +
                  help! 'Must supply a ruby file to load' unless @file_to_load
         
     | 
| 
      
 42 
     | 
    
         
            +
                  @file_to_load = ENV.fetch('PATH', '').split(File::PATH_SEPARATOR).push('.').reduce do |a, e|
         
     | 
| 
      
 43 
     | 
    
         
            +
                    next a if a
         
     | 
| 
      
 44 
     | 
    
         
            +
                    a ||= File.join(e, @file_to_load)
         
     | 
| 
      
 45 
     | 
    
         
            +
                    a &&= nil unless File.file?(a)
         
     | 
| 
      
 46 
     | 
    
         
            +
                    a
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
                  help! "Could not find `#{@file_to_load}`" unless @file_to_load
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                def run
         
     | 
| 
      
 52 
     | 
    
         
            +
                  argv = ::ARGV.dup
         
     | 
| 
      
 53 
     | 
    
         
            +
                  ::ARGV.replace(@arguments)
         
     | 
| 
      
 54 
     | 
    
         
            +
                  time { load(@file_to_load) }
         
     | 
| 
      
 55 
     | 
    
         
            +
                ensure
         
     | 
| 
      
 56 
     | 
    
         
            +
                  ::ARGV.replace(argv)
         
     | 
| 
      
 57 
     | 
    
         
            +
                end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                private
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                def time
         
     | 
| 
      
 62 
     | 
    
         
            +
                  timer = ::Chronometer.from_file(@chronofile, contents: @chronofile_contents)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  timer.install!
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 66 
     | 
    
         
            +
                    yield
         
     | 
| 
      
 67 
     | 
    
         
            +
                  ensure
         
     | 
| 
      
 68 
     | 
    
         
            +
                    timer.drain!
         
     | 
| 
      
 69 
     | 
    
         
            +
                    timer.print_trace_event_report(@output, metadata: { meta_success: $ERROR_INFO.nil? })
         
     | 
| 
      
 70 
     | 
    
         
            +
                  end
         
     | 
| 
      
 71 
     | 
    
         
            +
                end
         
     | 
| 
      
 72 
     | 
    
         
            +
              end
         
     | 
| 
      
 73 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,47 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class Chronometer
         
     | 
| 
      
 4 
     | 
    
         
            +
              class DSL
         
     | 
| 
      
 5 
     | 
    
         
            +
                attr_reader :events, :tracepoints
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                def initialize
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @events = []
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @tracepoints = []
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def for_class(cls)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @cls && raise('already in for_class')
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @cls = cls
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  yield
         
     | 
| 
      
 17 
     | 
    
         
            +
                ensure
         
     | 
| 
      
 18 
     | 
    
         
            +
                  @cls = nil
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                def for_singleton_class(cls, &blk)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  for_class(cls.singleton_class, &blk)
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                def method(method_name, **opts)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  opts[:name] ||= @cls.singleton_class? ? "#{ObjectSpace.each_object(@cls).to_a.last}.#{method_name}" : "#{@cls}##{method_name}"
         
     | 
| 
      
 27 
     | 
    
         
            +
                  opts.delete(:method) && raise('Cannot specify :method')
         
     | 
| 
      
 28 
     | 
    
         
            +
                  opts[:method] = method_name
         
     | 
| 
      
 29 
     | 
    
         
            +
                  opts[:event_type] ||= :X
         
     | 
| 
      
 30 
     | 
    
         
            +
                  opts[:cls] = @cls || raise('must be in for_class block')
         
     | 
| 
      
 31 
     | 
    
         
            +
                  events << Event.new(opts)
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                def methods(*method_names, **opts)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  method_names.flatten.each do |method_name|
         
     | 
| 
      
 36 
     | 
    
         
            +
                    method method_name, **opts
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                def tracepoint(event_name, &blk)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  @cls && raise('in for_class block')
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                  tracepoints << [event_name, blk]
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
              end
         
     | 
| 
      
 46 
     | 
    
         
            +
              private_constant :DSL
         
     | 
| 
      
 47 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,17 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class Chronometer
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Event
         
     | 
| 
      
 5 
     | 
    
         
            +
                attr_reader :cls, :method, :name, :category, :event_type, :context
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                def initialize(cls: nil, method: nil, name: nil, category: nil, event_type: nil, context: nil)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @cls = cls
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @method = method
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @name = name
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @category = category
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @event_type = event_type
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @context = context
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
              private_constant :Event
         
     | 
| 
      
 17 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,44 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class Chronometer
         
     | 
| 
      
 4 
     | 
    
         
            +
              class TraceEvent
         
     | 
| 
      
 5 
     | 
    
         
            +
                attr_reader :process_id, :thread_id, :start_time_usec, :event_type, :name, :args, :category, :duration, :cls, :method
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                def initialize(process_id: nil, thread_id: nil, start_time_usec: nil, event_type: nil, name: nil, args: nil, category: nil, duration: nil, cls: nil, method: nil)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @process_id = process_id
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @thread_id = thread_id
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @start_time_usec = start_time_usec
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @event_type = event_type
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @name = name
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @args = args
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @category = category
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @duration = duration
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @cls = cls
         
     | 
| 
      
 17 
     | 
    
         
            +
                  @method = method
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def to_h
         
     | 
| 
      
 21 
     | 
    
         
            +
                  compact_hash(
         
     | 
| 
      
 22 
     | 
    
         
            +
                    pid: process_id,
         
     | 
| 
      
 23 
     | 
    
         
            +
                    tid: thread_id,
         
     | 
| 
      
 24 
     | 
    
         
            +
                    ts: start_time_usec,
         
     | 
| 
      
 25 
     | 
    
         
            +
                    ph: event_type,
         
     | 
| 
      
 26 
     | 
    
         
            +
                    name: name,
         
     | 
| 
      
 27 
     | 
    
         
            +
                    args: args,
         
     | 
| 
      
 28 
     | 
    
         
            +
                    cat: category,
         
     | 
| 
      
 29 
     | 
    
         
            +
                    dur: duration
         
     | 
| 
      
 30 
     | 
    
         
            +
                  )
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                if {}.respond_to?(:compact)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  def compact_hash(hash)
         
     | 
| 
      
 35 
     | 
    
         
            +
                    hash.compact
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
                else
         
     | 
| 
      
 38 
     | 
    
         
            +
                  def compact_hash(hash)
         
     | 
| 
      
 39 
     | 
    
         
            +
                    hash.reject { |_k, v| v.nil? }
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
              end
         
     | 
| 
      
 43 
     | 
    
         
            +
              private_constant :TraceEvent
         
     | 
| 
      
 44 
     | 
    
         
            +
            end
         
     | 
    
        data/exe/chronometer
    ADDED
    
    
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,126 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: chronometer
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.1.0
         
     | 
| 
      
 5 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 6 
     | 
    
         
            +
            authors:
         
     | 
| 
      
 7 
     | 
    
         
            +
            - Samuel Giddins
         
     | 
| 
      
 8 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 9 
     | 
    
         
            +
            bindir: exe
         
     | 
| 
      
 10 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2018-03-28 00:00:00.000000000 Z
         
     | 
| 
      
 12 
     | 
    
         
            +
            dependencies:
         
     | 
| 
      
 13 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 14 
     | 
    
         
            +
              name: claide
         
     | 
| 
      
 15 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 16 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 17 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 18 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 19 
     | 
    
         
            +
                    version: '1.0'
         
     | 
| 
      
 20 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 21 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 22 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 23 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 24 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 25 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 26 
     | 
    
         
            +
                    version: '1.0'
         
     | 
| 
      
 27 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 28 
     | 
    
         
            +
              name: bundler
         
     | 
| 
      
 29 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 30 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 31 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 32 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 33 
     | 
    
         
            +
                    version: '1.16'
         
     | 
| 
      
 34 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 35 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 36 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 37 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 38 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 39 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 40 
     | 
    
         
            +
                    version: '1.16'
         
     | 
| 
      
 41 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 42 
     | 
    
         
            +
              name: rake
         
     | 
| 
      
 43 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 44 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 45 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 46 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 47 
     | 
    
         
            +
                    version: '10.5'
         
     | 
| 
      
 48 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 49 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 50 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 51 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 52 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 53 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 54 
     | 
    
         
            +
                    version: '10.5'
         
     | 
| 
      
 55 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 56 
     | 
    
         
            +
              name: rspec
         
     | 
| 
      
 57 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 58 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 59 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 60 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 61 
     | 
    
         
            +
                    version: '3.7'
         
     | 
| 
      
 62 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 63 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 64 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 65 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 66 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 67 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 68 
     | 
    
         
            +
                    version: '3.7'
         
     | 
| 
      
 69 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 70 
     | 
    
         
            +
              name: rubocop
         
     | 
| 
      
 71 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 72 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 73 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 74 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 75 
     | 
    
         
            +
                    version: 0.54.0
         
     | 
| 
      
 76 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 77 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 78 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 79 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 80 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 81 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 82 
     | 
    
         
            +
                    version: 0.54.0
         
     | 
| 
      
 83 
     | 
    
         
            +
            description: 
         
     | 
| 
      
 84 
     | 
    
         
            +
            email:
         
     | 
| 
      
 85 
     | 
    
         
            +
            - segiddins@segiddins.me
         
     | 
| 
      
 86 
     | 
    
         
            +
            executables:
         
     | 
| 
      
 87 
     | 
    
         
            +
            - chronometer
         
     | 
| 
      
 88 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 89 
     | 
    
         
            +
            extra_rdoc_files: []
         
     | 
| 
      
 90 
     | 
    
         
            +
            files:
         
     | 
| 
      
 91 
     | 
    
         
            +
            - "/Users/segiddins/Development/OpenSource/chronometer/CODE_OF_CONDUCT.md"
         
     | 
| 
      
 92 
     | 
    
         
            +
            - "/Users/segiddins/Development/OpenSource/chronometer/LICENSE.txt"
         
     | 
| 
      
 93 
     | 
    
         
            +
            - "/Users/segiddins/Development/OpenSource/chronometer/README.md"
         
     | 
| 
      
 94 
     | 
    
         
            +
            - "/Users/segiddins/Development/OpenSource/chronometer/exe/chronometer"
         
     | 
| 
      
 95 
     | 
    
         
            +
            - "/Users/segiddins/Development/OpenSource/chronometer/lib/chronometer.rb"
         
     | 
| 
      
 96 
     | 
    
         
            +
            - "/Users/segiddins/Development/OpenSource/chronometer/lib/chronometer/command.rb"
         
     | 
| 
      
 97 
     | 
    
         
            +
            - "/Users/segiddins/Development/OpenSource/chronometer/lib/chronometer/dsl.rb"
         
     | 
| 
      
 98 
     | 
    
         
            +
            - "/Users/segiddins/Development/OpenSource/chronometer/lib/chronometer/event.rb"
         
     | 
| 
      
 99 
     | 
    
         
            +
            - "/Users/segiddins/Development/OpenSource/chronometer/lib/chronometer/trace_event.rb"
         
     | 
| 
      
 100 
     | 
    
         
            +
            - "/Users/segiddins/Development/OpenSource/chronometer/lib/chronometer/version.rb"
         
     | 
| 
      
 101 
     | 
    
         
            +
            - exe/chronometer
         
     | 
| 
      
 102 
     | 
    
         
            +
            homepage: https://github.com/segiddins
         
     | 
| 
      
 103 
     | 
    
         
            +
            licenses:
         
     | 
| 
      
 104 
     | 
    
         
            +
            - MIT
         
     | 
| 
      
 105 
     | 
    
         
            +
            metadata: {}
         
     | 
| 
      
 106 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
      
 107 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 108 
     | 
    
         
            +
            require_paths:
         
     | 
| 
      
 109 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 110 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 111 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 112 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 113 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 114 
     | 
    
         
            +
                  version: '2.3'
         
     | 
| 
      
 115 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 116 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 117 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 118 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 119 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 120 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 121 
     | 
    
         
            +
            rubyforge_project: 
         
     | 
| 
      
 122 
     | 
    
         
            +
            rubygems_version: 2.7.3
         
     | 
| 
      
 123 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 124 
     | 
    
         
            +
            specification_version: 4
         
     | 
| 
      
 125 
     | 
    
         
            +
            summary: A library that makes generating Chrome trace files for Ruby programs easy.
         
     | 
| 
      
 126 
     | 
    
         
            +
            test_files: []
         
     |