nrser 0.2.0.pre.3 → 0.2.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 +4 -4
 - data/lib/nrser/ext/enumerable.rb +12 -3
 - data/lib/nrser/ext/module.rb +62 -0
 - data/lib/nrser/ext.rb +1 -0
 - data/lib/nrser/functions/binding.rb +33 -0
 - data/lib/nrser/functions/enumerable/associate.rb +103 -0
 - data/lib/nrser/functions/enumerable/map_keys.rb +0 -0
 - data/lib/nrser/functions/enumerable/map_values.rb +94 -0
 - data/lib/nrser/functions/enumerable.rb +2 -87
 - data/lib/nrser/functions/module/methods.rb +206 -0
 - data/lib/nrser/functions/module/source_locations.rb +213 -0
 - data/lib/nrser/functions/module.rb +2 -0
 - data/lib/nrser/functions.rb +1 -0
 - data/lib/nrser/logging/appender/sync.rb +148 -0
 - data/lib/nrser/logging/appender.rb +3 -0
 - data/lib/nrser/logging/formatters/color.rb +165 -0
 - data/lib/nrser/logging/formatters.rb +1 -0
 - data/lib/nrser/logging.rb +353 -0
 - data/lib/nrser/refinements/module.rb +5 -0
 - data/lib/nrser/refinements.rb +1 -0
 - data/lib/nrser/rspex/described.rb +99 -0
 - data/lib/nrser/rspex/example_group/describe_called_with.rb +2 -2
 - data/lib/nrser/rspex/example_group/describe_class.rb +31 -0
 - data/lib/nrser/rspex/example_group/describe_instance.rb +1 -1
 - data/lib/nrser/rspex/example_group/describe_method.rb +40 -0
 - data/lib/nrser/rspex/example_group.rb +2 -34
 - data/lib/nrser/rspex/format.rb +19 -6
 - data/lib/nrser/rspex.rb +1 -1
 - data/lib/nrser/types/numbers.rb +16 -16
 - data/lib/nrser/version.rb +1 -1
 - data/lib/nrser.rb +2 -5
 - data/spec/design/mapping_spec.rb +42 -0
 - data/spec/lib/nrser/mean_streak/identity_instance_spec.rb +7 -5
 - data/spec/spec_helper.rb +23 -105
 - data/spec/support/shared/types.rb +92 -0
 - data/spec/support/shared.rb +1 -0
 - metadata +27 -24
 - data/lib/nrser/labs/unicode_math.rb +0 -48
 - data/lib/nrser/labs/where.rb +0 -50
 - data/lib/nrser/logger.rb +0 -457
 - data/spec/lib/nrser/logger/dest_spec.rb +0 -15
 - data/spec/lib/nrser/logger/die_spec.rb +0 -41
 - data/spec/lib/nrser/logger/install_spec.rb +0 -98
 - data/spec/lib/nrser/logger/level_int_spec.rb +0 -22
 - data/spec/lib/nrser/logger/level_name_spec.rb +0 -23
 - data/spec/lib/nrser/logger/level_sym_spec.rb +0 -22
 - data/spec/lib/nrser/logger/send_log_spec.rb +0 -63
 - data/spec/lib/nrser/logger/use_spec.rb +0 -16
 
| 
         @@ -0,0 +1,213 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: UTF-8
         
     | 
| 
      
 2 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            using NRSER
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            # Definitions
         
     | 
| 
      
 7 
     | 
    
         
            +
            # =======================================================================
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            module NRSER
         
     | 
| 
      
 10 
     | 
    
         
            +
              
         
     | 
| 
      
 11 
     | 
    
         
            +
              # @!group Module Functions
         
     | 
| 
      
 12 
     | 
    
         
            +
              # ==========================================================================
         
     | 
| 
      
 13 
     | 
    
         
            +
              
         
     | 
| 
      
 14 
     | 
    
         
            +
              
         
     | 
| 
      
 15 
     | 
    
         
            +
              # @todo Document map_to_source_locations method.
         
     | 
| 
      
 16 
     | 
    
         
            +
              # 
         
     | 
| 
      
 17 
     | 
    
         
            +
              # @param [type] arg_name
         
     | 
| 
      
 18 
     | 
    
         
            +
              #   @todo Add name param description.
         
     | 
| 
      
 19 
     | 
    
         
            +
              # 
         
     | 
| 
      
 20 
     | 
    
         
            +
              # @return [Hash<#source_location, Array<(String?, Fixnum?)>?>]
         
     | 
| 
      
 21 
     | 
    
         
            +
              #   Map of objects
         
     | 
| 
      
 22 
     | 
    
         
            +
              # 
         
     | 
| 
      
 23 
     | 
    
         
            +
              def self.map_to_source_locations methods
         
     | 
| 
      
 24 
     | 
    
         
            +
                methods.assoc_to &:source_location
         
     | 
| 
      
 25 
     | 
    
         
            +
              end # .map_to_source_locations
         
     | 
| 
      
 26 
     | 
    
         
            +
              
         
     | 
| 
      
 27 
     | 
    
         
            +
              
         
     | 
| 
      
 28 
     | 
    
         
            +
              # Map class method {Methods} objects to the `#source_location` for `mod`
         
     | 
| 
      
 29 
     | 
    
         
            +
              # class methods.
         
     | 
| 
      
 30 
     | 
    
         
            +
              # 
         
     | 
| 
      
 31 
     | 
    
         
            +
              # @see https://ruby-doc.org/core/Method.html#method-i-source_location
         
     | 
| 
      
 32 
     | 
    
         
            +
              # 
         
     | 
| 
      
 33 
     | 
    
         
            +
              # @param (see NRSER.class_method_objects_for)
         
     | 
| 
      
 34 
     | 
    
         
            +
              # 
         
     | 
| 
      
 35 
     | 
    
         
            +
              # @return [Hash<Symbol, Array<(String?, Fixnum?)>?>]
         
     | 
| 
      
 36 
     | 
    
         
            +
              #   Hash mapping method name {Symbol}s to results of calling their
         
     | 
| 
      
 37 
     | 
    
         
            +
              #   {Method#source_location}, which seems to be able to be:
         
     | 
| 
      
 38 
     | 
    
         
            +
              #   
         
     | 
| 
      
 39 
     | 
    
         
            +
              #   1.  `Array<(String, Fixnum)>` - two-entry array of file path,
         
     | 
| 
      
 40 
     | 
    
         
            +
              #       line number.
         
     | 
| 
      
 41 
     | 
    
         
            +
              #   
         
     | 
| 
      
 42 
     | 
    
         
            +
              #   2.  `nil` - if this method was not defined in Ruby (C extension, etc.)
         
     | 
| 
      
 43 
     | 
    
         
            +
              #       
         
     | 
| 
      
 44 
     | 
    
         
            +
              #   3.  `Array<(nil, nil)>` - Not listed as a possibility in the docs, but
         
     | 
| 
      
 45 
     | 
    
         
            +
              #       I swear I've seen it, so watch out.
         
     | 
| 
      
 46 
     | 
    
         
            +
              # 
         
     | 
| 
      
 47 
     | 
    
         
            +
              def self.class_method_source_locations_for *args
         
     | 
| 
      
 48 
     | 
    
         
            +
                map_to_source_locations class_method_objects_for( *args )
         
     | 
| 
      
 49 
     | 
    
         
            +
              end # .class_method_source_locations
         
     | 
| 
      
 50 
     | 
    
         
            +
              
         
     | 
| 
      
 51 
     | 
    
         
            +
              
         
     | 
| 
      
 52 
     | 
    
         
            +
              # Map *own* (not inherited) class method {Methods} objects to the
         
     | 
| 
      
 53 
     | 
    
         
            +
              # `#source_location` for `mod` class methods.
         
     | 
| 
      
 54 
     | 
    
         
            +
              # 
         
     | 
| 
      
 55 
     | 
    
         
            +
              # @see https://ruby-doc.org/core/Method.html#method-i-source_location
         
     | 
| 
      
 56 
     | 
    
         
            +
              # 
         
     | 
| 
      
 57 
     | 
    
         
            +
              # @param  (see .own_class_method_objects_for)
         
     | 
| 
      
 58 
     | 
    
         
            +
              # @return (see .class_method_objects_for)
         
     | 
| 
      
 59 
     | 
    
         
            +
              # 
         
     | 
| 
      
 60 
     | 
    
         
            +
              def self.own_class_method_source_locations_for *args
         
     | 
| 
      
 61 
     | 
    
         
            +
                map_to_source_locations own_class_method_objects_for( *args )
         
     | 
| 
      
 62 
     | 
    
         
            +
              end # .own_class_method_source_locations_for
         
     | 
| 
      
 63 
     | 
    
         
            +
              
         
     | 
| 
      
 64 
     | 
    
         
            +
              
         
     | 
| 
      
 65 
     | 
    
         
            +
              # Map instance method {Methods} objects to the `#source_location` for `mod`
         
     | 
| 
      
 66 
     | 
    
         
            +
              # class methods.
         
     | 
| 
      
 67 
     | 
    
         
            +
              # 
         
     | 
| 
      
 68 
     | 
    
         
            +
              # @see https://ruby-doc.org/core/Method.html#method-i-source_location
         
     | 
| 
      
 69 
     | 
    
         
            +
              # 
         
     | 
| 
      
 70 
     | 
    
         
            +
              # @param (see .instance_method_objects_for)
         
     | 
| 
      
 71 
     | 
    
         
            +
              # @return (see .class_method_source_locations_for)
         
     | 
| 
      
 72 
     | 
    
         
            +
              # 
         
     | 
| 
      
 73 
     | 
    
         
            +
              def self.instance_method_source_locations_for *args
         
     | 
| 
      
 74 
     | 
    
         
            +
                map_to_source_locations instance_method_objects_for( *args )
         
     | 
| 
      
 75 
     | 
    
         
            +
              end # .class_method_source_locations
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
              # Map *own* (not inherited) class method {Methods} objects to the
         
     | 
| 
      
 79 
     | 
    
         
            +
              # `#source_location` for `mod` class methods.
         
     | 
| 
      
 80 
     | 
    
         
            +
              # 
         
     | 
| 
      
 81 
     | 
    
         
            +
              # @see https://ruby-doc.org/core/Method.html#method-i-source_location
         
     | 
| 
      
 82 
     | 
    
         
            +
              # 
         
     | 
| 
      
 83 
     | 
    
         
            +
              # @param  (see NRSER.own_class_method_objects_for)
         
     | 
| 
      
 84 
     | 
    
         
            +
              # @return (see NRSER.class_method_objects_for)
         
     | 
| 
      
 85 
     | 
    
         
            +
              # 
         
     | 
| 
      
 86 
     | 
    
         
            +
              def self.own_instance_method_source_locations_for *args
         
     | 
| 
      
 87 
     | 
    
         
            +
                map_to_source_locations own_instance_methods_objects_for( *args )
         
     | 
| 
      
 88 
     | 
    
         
            +
              end # .own_class_method_source_locations_for
         
     | 
| 
      
 89 
     | 
    
         
            +
              
         
     | 
| 
      
 90 
     | 
    
         
            +
              
         
     | 
| 
      
 91 
     | 
    
         
            +
              # @todo Document method_source_locations_for method.
         
     | 
| 
      
 92 
     | 
    
         
            +
              # 
         
     | 
| 
      
 93 
     | 
    
         
            +
              # @param [type] mod
         
     | 
| 
      
 94 
     | 
    
         
            +
              #   @todo Add name param description.
         
     | 
| 
      
 95 
     | 
    
         
            +
              # 
         
     | 
| 
      
 96 
     | 
    
         
            +
              # @return [return_type]
         
     | 
| 
      
 97 
     | 
    
         
            +
              #   @todo Document return value.
         
     | 
| 
      
 98 
     | 
    
         
            +
              # 
         
     | 
| 
      
 99 
     | 
    
         
            +
              def self.method_source_locations_for  mod,
         
     | 
| 
      
 100 
     | 
    
         
            +
                                                    include_super = false,
         
     | 
| 
      
 101 
     | 
    
         
            +
                                                    sort: true
         
     | 
| 
      
 102 
     | 
    
         
            +
                class_method_source_locations_for(
         
     | 
| 
      
 103 
     | 
    
         
            +
                  mod,
         
     | 
| 
      
 104 
     | 
    
         
            +
                  include_super,
         
     | 
| 
      
 105 
     | 
    
         
            +
                  sort: sort,
         
     | 
| 
      
 106 
     | 
    
         
            +
                ).
         
     | 
| 
      
 107 
     | 
    
         
            +
                  # map_keys { |name| ".#{ name }" }.
         
     | 
| 
      
 108 
     | 
    
         
            +
                  merge instance_method_source_locations_for(
         
     | 
| 
      
 109 
     | 
    
         
            +
                    mod,
         
     | 
| 
      
 110 
     | 
    
         
            +
                    include_super,
         
     | 
| 
      
 111 
     | 
    
         
            +
                    sort: sort,
         
     | 
| 
      
 112 
     | 
    
         
            +
                    # Think it makes sense to *always* include `#initialize` since at this
         
     | 
| 
      
 113 
     | 
    
         
            +
                    # point we're interested in where *all* the methods are, and that
         
     | 
| 
      
 114 
     | 
    
         
            +
                    # should def be included.
         
     | 
| 
      
 115 
     | 
    
         
            +
                    include_initialize: true,
         
     | 
| 
      
 116 
     | 
    
         
            +
                  ) # .map_keys { |name| "##{ name }" }
         
     | 
| 
      
 117 
     | 
    
         
            +
              end # .method_source_locations_for
         
     | 
| 
      
 118 
     | 
    
         
            +
              
         
     | 
| 
      
 119 
     | 
    
         
            +
              
         
     | 
| 
      
 120 
     | 
    
         
            +
              def self.own_method_source_locations_for  mod,
         
     | 
| 
      
 121 
     | 
    
         
            +
                                                        sort: true
         
     | 
| 
      
 122 
     | 
    
         
            +
                method_source_locations_for \
         
     | 
| 
      
 123 
     | 
    
         
            +
                  mod,
         
     | 
| 
      
 124 
     | 
    
         
            +
                  false,
         
     | 
| 
      
 125 
     | 
    
         
            +
                  sort: sort
         
     | 
| 
      
 126 
     | 
    
         
            +
              end # .method_source_locations_for
         
     | 
| 
      
 127 
     | 
    
         
            +
              
         
     | 
| 
      
 128 
     | 
    
         
            +
              
         
     | 
| 
      
 129 
     | 
    
         
            +
              
         
     | 
| 
      
 130 
     | 
    
         
            +
              # @todo Document module_source_locations method.
         
     | 
| 
      
 131 
     | 
    
         
            +
              # 
         
     | 
| 
      
 132 
     | 
    
         
            +
              # @param [type] arg_name
         
     | 
| 
      
 133 
     | 
    
         
            +
              #   @todo Add name param description.
         
     | 
| 
      
 134 
     | 
    
         
            +
              # 
         
     | 
| 
      
 135 
     | 
    
         
            +
              # @return [return_type]
         
     | 
| 
      
 136 
     | 
    
         
            +
              #   @todo Document return value.
         
     | 
| 
      
 137 
     | 
    
         
            +
              # 
         
     | 
| 
      
 138 
     | 
    
         
            +
              def self.module_source_locations mod
         
     | 
| 
      
 139 
     | 
    
         
            +
                # Get all the src locs for `mod`'s methods
         
     | 
| 
      
 140 
     | 
    
         
            +
                own_method_source_locations_for( mod ).values.
         
     | 
| 
      
 141 
     | 
    
         
            +
                  # Filter out any that don't have full src loc info
         
     | 
| 
      
 142 
     | 
    
         
            +
                  reject { |src_loc| src_loc.nil? || src_loc.any?( &:nil? ) }
         
     | 
| 
      
 143 
     | 
    
         
            +
              end # .module_source_locations
         
     | 
| 
      
 144 
     | 
    
         
            +
              
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
              
         
     | 
| 
      
 147 
     | 
    
         
            +
              # Get a reasonable file and line for the class.
         
     | 
| 
      
 148 
     | 
    
         
            +
              # 
         
     | 
| 
      
 149 
     | 
    
         
            +
              # @param [Class] cls
         
     | 
| 
      
 150 
     | 
    
         
            +
              #   Class to try and locate.
         
     | 
| 
      
 151 
     | 
    
         
            +
              # 
         
     | 
| 
      
 152 
     | 
    
         
            +
              # @return [Array<(String, Fixnum)>]
         
     | 
| 
      
 153 
     | 
    
         
            +
              #   Two entry array; first entry is the string file path, second is the
         
     | 
| 
      
 154 
     | 
    
         
            +
              #   line number.
         
     | 
| 
      
 155 
     | 
    
         
            +
              # 
         
     | 
| 
      
 156 
     | 
    
         
            +
              def self.module_source_location mod
         
     | 
| 
      
 157 
     | 
    
         
            +
                # If any files end with the "canonical path" then use that. It's a path
         
     | 
| 
      
 158 
     | 
    
         
            +
                # suffix
         
     | 
| 
      
 159 
     | 
    
         
            +
                # 
         
     | 
| 
      
 160 
     | 
    
         
            +
                #     "my_mod/sub_mod/some_class.rb"
         
     | 
| 
      
 161 
     | 
    
         
            +
                # 
         
     | 
| 
      
 162 
     | 
    
         
            +
                # the for a class
         
     | 
| 
      
 163 
     | 
    
         
            +
                # 
         
     | 
| 
      
 164 
     | 
    
         
            +
                #     MyMod::SubMod::SomeClass
         
     | 
| 
      
 165 
     | 
    
         
            +
                # 
         
     | 
| 
      
 166 
     | 
    
         
            +
                canonical_path_end = \
         
     | 
| 
      
 167 
     | 
    
         
            +
                  ActiveSupport::Inflector.underscore( mod.name ) + '.rb'
         
     | 
| 
      
 168 
     | 
    
         
            +
                
         
     | 
| 
      
 169 
     | 
    
         
            +
                # Get all the src locs for `mod`'s methods
         
     | 
| 
      
 170 
     | 
    
         
            +
                src_locs = module_source_locations mod
         
     | 
| 
      
 171 
     | 
    
         
            +
                
         
     | 
| 
      
 172 
     | 
    
         
            +
                # Find first line in canonical path (if any)
         
     | 
| 
      
 173 
     | 
    
         
            +
                canonical_path_src_loc = src_locs.
         
     | 
| 
      
 174 
     | 
    
         
            +
                  find_all { |(path, line)| path.end_with? canonical_path_end }.
         
     | 
| 
      
 175 
     | 
    
         
            +
                  min_by { |(path, line)| line }
         
     | 
| 
      
 176 
     | 
    
         
            +
                
         
     | 
| 
      
 177 
     | 
    
         
            +
                # If we found one, we're done!
         
     | 
| 
      
 178 
     | 
    
         
            +
                return canonical_path_src_loc if canonical_path_src_loc
         
     | 
| 
      
 179 
     | 
    
         
            +
                
         
     | 
| 
      
 180 
     | 
    
         
            +
                raise "HERE"
         
     | 
| 
      
 181 
     | 
    
         
            +
                
         
     | 
| 
      
 182 
     | 
    
         
            +
                klass.
         
     | 
| 
      
 183 
     | 
    
         
            +
                  # Get an array of all instance methods, excluding inherited ones
         
     | 
| 
      
 184 
     | 
    
         
            +
                  # (the `false` arg)
         
     | 
| 
      
 185 
     | 
    
         
            +
                  instance_methods( false ).
         
     | 
| 
      
 186 
     | 
    
         
            +
                  # Add `#initialize` since it isn't in `#instance_methods` for some
         
     | 
| 
      
 187 
     | 
    
         
            +
                  # reason
         
     | 
| 
      
 188 
     | 
    
         
            +
                  <<( :initialize ).
         
     | 
| 
      
 189 
     | 
    
         
            +
                  # Map those to their {UnboundMethod} objects
         
     | 
| 
      
 190 
     | 
    
         
            +
                  map { |sym| klass.instance_method sym }.
         
     | 
| 
      
 191 
     | 
    
         
            +
                  # Toss any `nil` values (TODO how/why?)
         
     | 
| 
      
 192 
     | 
    
         
            +
                  compact.
         
     | 
| 
      
 193 
     | 
    
         
            +
                  # Get the source locations
         
     | 
| 
      
 194 
     | 
    
         
            +
                  map( &:source_location ).
         
     | 
| 
      
 195 
     | 
    
         
            +
                  # Get rid of `[nil, nil]` results, which seems to come from C exts?
         
     | 
| 
      
 196 
     | 
    
         
            +
                  reject { |(path, line)| path.nil? || line.nil? }.
         
     | 
| 
      
 197 
     | 
    
         
            +
                  # Get the first line in the shortest path
         
     | 
| 
      
 198 
     | 
    
         
            +
                  min_by { |(path, line)| [path.length, line] }
         
     | 
| 
      
 199 
     | 
    
         
            +
                  
         
     | 
| 
      
 200 
     | 
    
         
            +
                  # Another approach I thought of... (untested)
         
     | 
| 
      
 201 
     | 
    
         
            +
                  # 
         
     | 
| 
      
 202 
     | 
    
         
            +
                  # Get the path
         
     | 
| 
      
 203 
     | 
    
         
            +
                  # # Get frequency of the paths
         
     | 
| 
      
 204 
     | 
    
         
            +
                  # count_by { |(path, line)| path }.
         
     | 
| 
      
 205 
     | 
    
         
            +
                  # # Get the one with the most occurrences
         
     | 
| 
      
 206 
     | 
    
         
            +
                  # max_by { |path, count| count }.
         
     | 
| 
      
 207 
     | 
    
         
            +
                  # # Get just the path (not the count)
         
     | 
| 
      
 208 
     | 
    
         
            +
                  # first
         
     | 
| 
      
 209 
     | 
    
         
            +
              end # .module_source_location
         
     | 
| 
      
 210 
     | 
    
         
            +
              
         
     | 
| 
      
 211 
     | 
    
         
            +
              # @!endgroup Module Functions
         
     | 
| 
      
 212 
     | 
    
         
            +
              
         
     | 
| 
      
 213 
     | 
    
         
            +
            end # module NRSER
         
     | 
    
        data/lib/nrser/functions.rb
    CHANGED
    
    
| 
         @@ -0,0 +1,148 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: UTF-8
         
     | 
| 
      
 2 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            # Definitions
         
     | 
| 
      
 6 
     | 
    
         
            +
            # =======================================================================
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            # Replacement for {SemanticLogger::Appender::Async} that implements the
         
     | 
| 
      
 9 
     | 
    
         
            +
            # same interface but just logs synchronously in the current thread.
         
     | 
| 
      
 10 
     | 
    
         
            +
            # 
         
     | 
| 
      
 11 
     | 
    
         
            +
            # Basically just implements the {SemanticLogger::Appender::Async} API,
         
     | 
| 
      
 12 
     | 
    
         
            +
            # returning mostly with fake / nonsense values, but it seems to work, and
         
     | 
| 
      
 13 
     | 
    
         
            +
            # just let's writes go strait through to the {#appender} (which is actually
         
     | 
| 
      
 14 
     | 
    
         
            +
            # a {SemanticLogger::Processor}).
         
     | 
| 
      
 15 
     | 
    
         
            +
            # 
         
     | 
| 
      
 16 
     | 
    
         
            +
            # Useful for CLI applications where you want to see output in sync with
         
     | 
| 
      
 17 
     | 
    
         
            +
            # operations.
         
     | 
| 
      
 18 
     | 
    
         
            +
            # 
         
     | 
| 
      
 19 
     | 
    
         
            +
            class NRSER::Logging::Appender::Sync
         
     | 
| 
      
 20 
     | 
    
         
            +
              
         
     | 
| 
      
 21 
     | 
    
         
            +
              # Mixins
         
     | 
| 
      
 22 
     | 
    
         
            +
              # ============================================================================
         
     | 
| 
      
 23 
     | 
    
         
            +
              
         
     | 
| 
      
 24 
     | 
    
         
            +
              # Macros for forwarding to {#appender}
         
     | 
| 
      
 25 
     | 
    
         
            +
              extend Forwardable
         
     | 
| 
      
 26 
     | 
    
         
            +
              
         
     | 
| 
      
 27 
     | 
    
         
            +
              
         
     | 
| 
      
 28 
     | 
    
         
            +
              # 
         
     | 
| 
      
 29 
     | 
    
         
            +
              # ============================================================================
         
     | 
| 
      
 30 
     | 
    
         
            +
              
         
     | 
| 
      
 31 
     | 
    
         
            +
              # The appender we forward to, which is a {SemanticLogger::Processor}
         
     | 
| 
      
 32 
     | 
    
         
            +
              # in practice, since it wouldn't make any sense to wrap a regular
         
     | 
| 
      
 33 
     | 
    
         
            +
              # appender in a Sync.
         
     | 
| 
      
 34 
     | 
    
         
            +
              # 
         
     | 
| 
      
 35 
     | 
    
         
            +
              # @return [SemanticLogger::Processor]
         
     | 
| 
      
 36 
     | 
    
         
            +
              #     
         
     | 
| 
      
 37 
     | 
    
         
            +
              attr_accessor :appender
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
              # Forward methods that can be called directly
         
     | 
| 
      
 40 
     | 
    
         
            +
              def_delegator :@appender, :name
         
     | 
| 
      
 41 
     | 
    
         
            +
              def_delegator :@appender, :should_log?
         
     | 
| 
      
 42 
     | 
    
         
            +
              def_delegator :@appender, :filter
         
     | 
| 
      
 43 
     | 
    
         
            +
              def_delegator :@appender, :host
         
     | 
| 
      
 44 
     | 
    
         
            +
              def_delegator :@appender, :application
         
     | 
| 
      
 45 
     | 
    
         
            +
              def_delegator :@appender, :level
         
     | 
| 
      
 46 
     | 
    
         
            +
              def_delegator :@appender, :level=
         
     | 
| 
      
 47 
     | 
    
         
            +
              def_delegator :@appender, :logger
         
     | 
| 
      
 48 
     | 
    
         
            +
              
         
     | 
| 
      
 49 
     | 
    
         
            +
              # Added for sync
         
     | 
| 
      
 50 
     | 
    
         
            +
              def_delegator :@appender, :log
         
     | 
| 
      
 51 
     | 
    
         
            +
              def_delegator :@appender, :on_log
         
     | 
| 
      
 52 
     | 
    
         
            +
              def_delegator :@appender, :flush
         
     | 
| 
      
 53 
     | 
    
         
            +
              def_delegator :@appender, :close
         
     | 
| 
      
 54 
     | 
    
         
            +
              
         
     | 
| 
      
 55 
     | 
    
         
            +
              
         
     | 
| 
      
 56 
     | 
    
         
            +
              # A fake {Queue} that just implements a {.size} method that returns `0`.
         
     | 
| 
      
 57 
     | 
    
         
            +
              # 
         
     | 
| 
      
 58 
     | 
    
         
            +
              # Sync appender doesn't need a queue, but Semantic Logger expects one, so
         
     | 
| 
      
 59 
     | 
    
         
            +
              # telling it the length is always zero seems to make sense.
         
     | 
| 
      
 60 
     | 
    
         
            +
              # 
         
     | 
| 
      
 61 
     | 
    
         
            +
              class FakeQueue
         
     | 
| 
      
 62 
     | 
    
         
            +
                # @return [0]
         
     | 
| 
      
 63 
     | 
    
         
            +
                #   Fake queue is always empty.
         
     | 
| 
      
 64 
     | 
    
         
            +
                def self.size
         
     | 
| 
      
 65 
     | 
    
         
            +
                  0
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
              end # class FakeQueue
         
     | 
| 
      
 68 
     | 
    
         
            +
              
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
              # Construct a sync appender.
         
     | 
| 
      
 71 
     | 
    
         
            +
              #
         
     | 
| 
      
 72 
     | 
    
         
            +
              # @param [SemanticLogger]
         
     | 
| 
      
 73 
     | 
    
         
            +
              #   name: [String]
         
     | 
| 
      
 74 
     | 
    
         
            +
              #     Name to use for the log thread and the log name when logging any errors from this appender.
         
     | 
| 
      
 75 
     | 
    
         
            +
              #
         
     | 
| 
      
 76 
     | 
    
         
            +
              #   lag_threshold_s [Float]
         
     | 
| 
      
 77 
     | 
    
         
            +
              #     Log a warning when a log message has been on the queue for longer than this period in seconds.
         
     | 
| 
      
 78 
     | 
    
         
            +
              #     Default: 30
         
     | 
| 
      
 79 
     | 
    
         
            +
              #
         
     | 
| 
      
 80 
     | 
    
         
            +
              #   lag_check_interval: [Integer]
         
     | 
| 
      
 81 
     | 
    
         
            +
              #     Number of messages to process before checking for slow logging.
         
     | 
| 
      
 82 
     | 
    
         
            +
              #     Default: 1,000
         
     | 
| 
      
 83 
     | 
    
         
            +
              def initialize  appender:, name: appender.class.name
         
     | 
| 
      
 84 
     | 
    
         
            +
                @appender = appender
         
     | 
| 
      
 85 
     | 
    
         
            +
              end
         
     | 
| 
      
 86 
     | 
    
         
            +
              
         
     | 
| 
      
 87 
     | 
    
         
            +
              # Needs to be there to support {SemanticLogger::Processor.queue_size},
         
     | 
| 
      
 88 
     | 
    
         
            +
              # which gets the queue and returns it's size (which will always be zero
         
     | 
| 
      
 89 
     | 
    
         
            +
              # for us).
         
     | 
| 
      
 90 
     | 
    
         
            +
              # 
         
     | 
| 
      
 91 
     | 
    
         
            +
              # We return {FakeQueue}, which only implements a `size` method that
         
     | 
| 
      
 92 
     | 
    
         
            +
              # returns zero.
         
     | 
| 
      
 93 
     | 
    
         
            +
              # 
         
     | 
| 
      
 94 
     | 
    
         
            +
              # @return [#size]
         
     | 
| 
      
 95 
     | 
    
         
            +
              # 
         
     | 
| 
      
 96 
     | 
    
         
            +
              def queue; FakeQueue; end
         
     | 
| 
      
 97 
     | 
    
         
            +
              
         
     | 
| 
      
 98 
     | 
    
         
            +
              
         
     | 
| 
      
 99 
     | 
    
         
            +
              # @return [-1]
         
     | 
| 
      
 100 
     | 
    
         
            +
              #   Nonsense value meant to indicate there is no lag check interval.
         
     | 
| 
      
 101 
     | 
    
         
            +
              def lag_check_interval; -1; end
         
     | 
| 
      
 102 
     | 
    
         
            +
              
         
     | 
| 
      
 103 
     | 
    
         
            +
              
         
     | 
| 
      
 104 
     | 
    
         
            +
              # @raise [NotImplementedError]
         
     | 
| 
      
 105 
     | 
    
         
            +
              #   Sync appender doesn't support setting lag check interval.
         
     | 
| 
      
 106 
     | 
    
         
            +
              def lag_check_interval= value
         
     | 
| 
      
 107 
     | 
    
         
            +
                raise NotImplementedError,
         
     | 
| 
      
 108 
     | 
    
         
            +
                  "Can't set `lag_check_interval` on Sync appender"
         
     | 
| 
      
 109 
     | 
    
         
            +
              end
         
     | 
| 
      
 110 
     | 
    
         
            +
              
         
     | 
| 
      
 111 
     | 
    
         
            +
              
         
     | 
| 
      
 112 
     | 
    
         
            +
              # @return [-1]
         
     | 
| 
      
 113 
     | 
    
         
            +
              #   Nonsense value meant to indicate there is no lag threshold.
         
     | 
| 
      
 114 
     | 
    
         
            +
              def lag_threshold_s; -1; end
         
     | 
| 
      
 115 
     | 
    
         
            +
              
         
     | 
| 
      
 116 
     | 
    
         
            +
              
         
     | 
| 
      
 117 
     | 
    
         
            +
              # @raise [NotImplementedError]
         
     | 
| 
      
 118 
     | 
    
         
            +
              #   Sync appender doesn't support setting log threshold.
         
     | 
| 
      
 119 
     | 
    
         
            +
              def lag_threshold_s= value
         
     | 
| 
      
 120 
     | 
    
         
            +
                raise NotImplementedError,
         
     | 
| 
      
 121 
     | 
    
         
            +
                  "Can't set `lag_threshold_s` on Sync appender"
         
     | 
| 
      
 122 
     | 
    
         
            +
              end
         
     | 
| 
      
 123 
     | 
    
         
            +
              
         
     | 
| 
      
 124 
     | 
    
         
            +
              
         
     | 
| 
      
 125 
     | 
    
         
            +
              # @return [false]
         
     | 
| 
      
 126 
     | 
    
         
            +
              #   Sync appender is of course not size-capped.
         
     | 
| 
      
 127 
     | 
    
         
            +
              def capped?; false; end
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
              
         
     | 
| 
      
 130 
     | 
    
         
            +
              # The {SemanticLogger::Appender::Async} worker thread is exposed via
         
     | 
| 
      
 131 
     | 
    
         
            +
              # this method, which creates it if it doesn't exist and returns it, but
         
     | 
| 
      
 132 
     | 
    
         
            +
              # it doesn't seem like the returned value is ever used; the method
         
     | 
| 
      
 133 
     | 
    
         
            +
              # call is just invoked to start the thread.
         
     | 
| 
      
 134 
     | 
    
         
            +
              # 
         
     | 
| 
      
 135 
     | 
    
         
            +
              # Hence it seems to make most sense to just return `nil` since we don't
         
     | 
| 
      
 136 
     | 
    
         
            +
              # have a thread, and figure out what to do if that causes errors (so far
         
     | 
| 
      
 137 
     | 
    
         
            +
              # it seems fine).
         
     | 
| 
      
 138 
     | 
    
         
            +
              #
         
     | 
| 
      
 139 
     | 
    
         
            +
              # @return [nil]
         
     | 
| 
      
 140 
     | 
    
         
            +
              # 
         
     | 
| 
      
 141 
     | 
    
         
            +
              def thread; end
         
     | 
| 
      
 142 
     | 
    
         
            +
              
         
     | 
| 
      
 143 
     | 
    
         
            +
              
         
     | 
| 
      
 144 
     | 
    
         
            +
              # @return [true]
         
     | 
| 
      
 145 
     | 
    
         
            +
              #   Sync appender is always active
         
     | 
| 
      
 146 
     | 
    
         
            +
              def active?; true; end
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
            end # class NRSER::Logging::Appender::Sync
         
     | 
| 
         @@ -0,0 +1,165 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Requirements
         
     | 
| 
      
 2 
     | 
    
         
            +
            # =======================================================================
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            # Stdlib
         
     | 
| 
      
 5 
     | 
    
         
            +
            # -----------------------------------------------------------------------
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            # Deps
         
     | 
| 
      
 8 
     | 
    
         
            +
            # -----------------------------------------------------------------------
         
     | 
| 
      
 9 
     | 
    
         
            +
            require 'awesome_print'
         
     | 
| 
      
 10 
     | 
    
         
            +
            require 'semantic_logger'
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            # Project / Package
         
     | 
| 
      
 13 
     | 
    
         
            +
            # -----------------------------------------------------------------------
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            # Refinements
         
     | 
| 
      
 17 
     | 
    
         
            +
            # =======================================================================
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            # Declarations
         
     | 
| 
      
 21 
     | 
    
         
            +
            # =======================================================================
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            module NRSER::Logging; end
         
     | 
| 
      
 24 
     | 
    
         
            +
            module NRSER::Logging::Formatters; end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            # Definitions
         
     | 
| 
      
 28 
     | 
    
         
            +
            # =======================================================================
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            class NRSER::Logging::Formatters::Color < ::SemanticLogger::Formatters::Color
         
     | 
| 
      
 31 
     | 
    
         
            +
              
         
     | 
| 
      
 32 
     | 
    
         
            +
              # Constants
         
     | 
| 
      
 33 
     | 
    
         
            +
              # ======================================================================
         
     | 
| 
      
 34 
     | 
    
         
            +
              
         
     | 
| 
      
 35 
     | 
    
         
            +
              # ANSI escape sequence to start "Dark Gray" color.
         
     | 
| 
      
 36 
     | 
    
         
            +
              # 
         
     | 
| 
      
 37 
     | 
    
         
            +
              # @return [String]
         
     | 
| 
      
 38 
     | 
    
         
            +
              # 
         
     | 
| 
      
 39 
     | 
    
         
            +
              ANSI_ESC_DARK_GRAY = "\e[1;30m"
         
     | 
| 
      
 40 
     | 
    
         
            +
              
         
     | 
| 
      
 41 
     | 
    
         
            +
              
         
     | 
| 
      
 42 
     | 
    
         
            +
              # Class Methods
         
     | 
| 
      
 43 
     | 
    
         
            +
              # ======================================================================
         
     | 
| 
      
 44 
     | 
    
         
            +
              
         
     | 
| 
      
 45 
     | 
    
         
            +
              # @todo Document default_color_map method.
         
     | 
| 
      
 46 
     | 
    
         
            +
              # 
         
     | 
| 
      
 47 
     | 
    
         
            +
              # @param [type] arg_name
         
     | 
| 
      
 48 
     | 
    
         
            +
              #   @todo Add name param description.
         
     | 
| 
      
 49 
     | 
    
         
            +
              # 
         
     | 
| 
      
 50 
     | 
    
         
            +
              # @return [SemanticLogger::Formatters::Color::ColorMap]
         
     | 
| 
      
 51 
     | 
    
         
            +
              # 
         
     | 
| 
      
 52 
     | 
    
         
            +
              def self.default_color_map
         
     | 
| 
      
 53 
     | 
    
         
            +
                SemanticLogger::Formatters::Color::ColorMap.new(
         
     | 
| 
      
 54 
     | 
    
         
            +
                  debug: SemanticLogger::AnsiColors::MAGENTA,
         
     | 
| 
      
 55 
     | 
    
         
            +
                  trace: ANSI_ESC_DARK_GRAY,
         
     | 
| 
      
 56 
     | 
    
         
            +
                )
         
     | 
| 
      
 57 
     | 
    
         
            +
              end # .default_color_map
         
     | 
| 
      
 58 
     | 
    
         
            +
              
         
     | 
| 
      
 59 
     | 
    
         
            +
              
         
     | 
| 
      
 60 
     | 
    
         
            +
              # Attributes
         
     | 
| 
      
 61 
     | 
    
         
            +
              # ======================================================================
         
     | 
| 
      
 62 
     | 
    
         
            +
              
         
     | 
| 
      
 63 
     | 
    
         
            +
              
         
     | 
| 
      
 64 
     | 
    
         
            +
              # Constructor
         
     | 
| 
      
 65 
     | 
    
         
            +
              # ======================================================================
         
     | 
| 
      
 66 
     | 
    
         
            +
              
         
     | 
| 
      
 67 
     | 
    
         
            +
              # Instantiate a new `ColorFormatter`.
         
     | 
| 
      
 68 
     | 
    
         
            +
              def initialize  ap: {multiline: true},
         
     | 
| 
      
 69 
     | 
    
         
            +
                              color_map: self.class.default_color_map,
         
     | 
| 
      
 70 
     | 
    
         
            +
                              time_format: ::SemanticLogger::Formatters::Base::TIME_FORMAT,
         
     | 
| 
      
 71 
     | 
    
         
            +
                              log_host: false,
         
     | 
| 
      
 72 
     | 
    
         
            +
                              log_application: false
         
     | 
| 
      
 73 
     | 
    
         
            +
                super ap: ap,
         
     | 
| 
      
 74 
     | 
    
         
            +
                      color_map: color_map,
         
     | 
| 
      
 75 
     | 
    
         
            +
                      time_format: time_format,
         
     | 
| 
      
 76 
     | 
    
         
            +
                      log_host: log_host,
         
     | 
| 
      
 77 
     | 
    
         
            +
                      log_application: log_application
         
     | 
| 
      
 78 
     | 
    
         
            +
              end # #initialize
         
     | 
| 
      
 79 
     | 
    
         
            +
              
         
     | 
| 
      
 80 
     | 
    
         
            +
              
         
     | 
| 
      
 81 
     | 
    
         
            +
              # Instance Methods
         
     | 
| 
      
 82 
     | 
    
         
            +
              # ======================================================================
         
     | 
| 
      
 83 
     | 
    
         
            +
              
         
     | 
| 
      
 84 
     | 
    
         
            +
              
         
     | 
| 
      
 85 
     | 
    
         
            +
              # Upcase the log level.
         
     | 
| 
      
 86 
     | 
    
         
            +
              # 
         
     | 
| 
      
 87 
     | 
    
         
            +
              # @return [String]
         
     | 
| 
      
 88 
     | 
    
         
            +
              # 
         
     | 
| 
      
 89 
     | 
    
         
            +
              def level
         
     | 
| 
      
 90 
     | 
    
         
            +
                "#{ color }#{ log.level.upcase }#{ color_map.clear }"
         
     | 
| 
      
 91 
     | 
    
         
            +
              end
         
     | 
| 
      
 92 
     | 
    
         
            +
              
         
     | 
| 
      
 93 
     | 
    
         
            +
              
         
     | 
| 
      
 94 
     | 
    
         
            +
              # Create the log entry text. Overridden to customize appearance -
         
     | 
| 
      
 95 
     | 
    
         
            +
              # generally reduce amount of info and put payload on it's own line.
         
     | 
| 
      
 96 
     | 
    
         
            +
              # 
         
     | 
| 
      
 97 
     | 
    
         
            +
              # We need to replace *two* super functions, the first being
         
     | 
| 
      
 98 
     | 
    
         
            +
              # [SemanticLogger::Formatters::Color#call][]:
         
     | 
| 
      
 99 
     | 
    
         
            +
              # 
         
     | 
| 
      
 100 
     | 
    
         
            +
              #     def call(log, logger)
         
     | 
| 
      
 101 
     | 
    
         
            +
              #       self.color = color_map[log.level]
         
     | 
| 
      
 102 
     | 
    
         
            +
              #       super(log, logger)
         
     | 
| 
      
 103 
     | 
    
         
            +
              #     end
         
     | 
| 
      
 104 
     | 
    
         
            +
              # 
         
     | 
| 
      
 105 
     | 
    
         
            +
              # [SemanticLogger::Formatters::Color#call]: https://github.com/rocketjob/semantic_logger/blob/v4.2.0/lib/semantic_logger/formatters/color.rb#L98
         
     | 
| 
      
 106 
     | 
    
         
            +
              # 
         
     | 
| 
      
 107 
     | 
    
         
            +
              # which doesn't do all too much, and the next being it's super-method,
         
     | 
| 
      
 108 
     | 
    
         
            +
              # [SemanticLogger::Formatters::Default#call][]:
         
     | 
| 
      
 109 
     | 
    
         
            +
              #     
         
     | 
| 
      
 110 
     | 
    
         
            +
              #     # Default text log format
         
     | 
| 
      
 111 
     | 
    
         
            +
              #     #  Generates logs of the form:
         
     | 
| 
      
 112 
     | 
    
         
            +
              #     #    2011-07-19 14:36:15.660235 D [1149:ScriptThreadProcess] Rails -- Hello World
         
     | 
| 
      
 113 
     | 
    
         
            +
              #     def call(log, logger)
         
     | 
| 
      
 114 
     | 
    
         
            +
              #       self.log    = log
         
     | 
| 
      
 115 
     | 
    
         
            +
              #       self.logger = logger
         
     | 
| 
      
 116 
     | 
    
         
            +
              #     
         
     | 
| 
      
 117 
     | 
    
         
            +
              #       [time, level, process_info, tags, named_tags, duration, name, message, payload, exception].compact.join(' ')
         
     | 
| 
      
 118 
     | 
    
         
            +
              #     end
         
     | 
| 
      
 119 
     | 
    
         
            +
              # 
         
     | 
| 
      
 120 
     | 
    
         
            +
              # [SemanticLogger::Formatters::Default#call]: https://github.com/rocketjob/semantic_logger/blob/v4.2.0/lib/semantic_logger/formatters/default.rb#L64
         
     | 
| 
      
 121 
     | 
    
         
            +
              # 
         
     | 
| 
      
 122 
     | 
    
         
            +
              # which does most the real assembly.
         
     | 
| 
      
 123 
     | 
    
         
            +
              # 
         
     | 
| 
      
 124 
     | 
    
         
            +
              # @param [SemanticLogger::Log] log
         
     | 
| 
      
 125 
     | 
    
         
            +
              #   The log entry to format.
         
     | 
| 
      
 126 
     | 
    
         
            +
              #   
         
     | 
| 
      
 127 
     | 
    
         
            +
              #   See [SemanticLogger::Log](https://github.com/rocketjob/semantic_logger/blob/v4.2.0/lib/semantic_logger/log.rb)
         
     | 
| 
      
 128 
     | 
    
         
            +
              # 
         
     | 
| 
      
 129 
     | 
    
         
            +
              # @param [SemanticLogger::Logger] logger
         
     | 
| 
      
 130 
     | 
    
         
            +
              #   The logger doing the logging (pretty sure, haven't checked).
         
     | 
| 
      
 131 
     | 
    
         
            +
              #   
         
     | 
| 
      
 132 
     | 
    
         
            +
              #   See [SemanticLogger::Logger](https://github.com/rocketjob/semantic_logger/blob/v4.2.0/lib/semantic_logger/logger.rb)
         
     | 
| 
      
 133 
     | 
    
         
            +
              # 
         
     | 
| 
      
 134 
     | 
    
         
            +
              # @return [return_type]
         
     | 
| 
      
 135 
     | 
    
         
            +
              #   @todo Document return value.
         
     | 
| 
      
 136 
     | 
    
         
            +
              # 
         
     | 
| 
      
 137 
     | 
    
         
            +
              def call log, logger
         
     | 
| 
      
 138 
     | 
    
         
            +
                # SemanticLogger::Formatters::Color code
         
     | 
| 
      
 139 
     | 
    
         
            +
                self.color = color_map[log.level]
         
     | 
| 
      
 140 
     | 
    
         
            +
                
         
     | 
| 
      
 141 
     | 
    
         
            +
                # SemanticLogger::Formatters::Default code
         
     | 
| 
      
 142 
     | 
    
         
            +
                self.log    = log
         
     | 
| 
      
 143 
     | 
    
         
            +
                self.logger = logger
         
     | 
| 
      
 144 
     | 
    
         
            +
                
         
     | 
| 
      
 145 
     | 
    
         
            +
                [
         
     | 
| 
      
 146 
     | 
    
         
            +
                  time, # annoyingly noisy and don't really need for local CLI app
         
     | 
| 
      
 147 
     | 
    
         
            +
                  level,
         
     | 
| 
      
 148 
     | 
    
         
            +
                  process_info,
         
     | 
| 
      
 149 
     | 
    
         
            +
                  tags,
         
     | 
| 
      
 150 
     | 
    
         
            +
                  named_tags,
         
     | 
| 
      
 151 
     | 
    
         
            +
                  duration,
         
     | 
| 
      
 152 
     | 
    
         
            +
                  name,
         
     | 
| 
      
 153 
     | 
    
         
            +
                ].compact.join( ' ' ) +
         
     | 
| 
      
 154 
     | 
    
         
            +
                "\n" +
         
     | 
| 
      
 155 
     | 
    
         
            +
                [
         
     | 
| 
      
 156 
     | 
    
         
            +
                  message,
         
     | 
| 
      
 157 
     | 
    
         
            +
                  payload,
         
     | 
| 
      
 158 
     | 
    
         
            +
                  exception,
         
     | 
| 
      
 159 
     | 
    
         
            +
                ].compact.join(' ') +
         
     | 
| 
      
 160 
     | 
    
         
            +
                "\n" # I like extra newline to space shit out
         
     | 
| 
      
 161 
     | 
    
         
            +
                
         
     | 
| 
      
 162 
     | 
    
         
            +
              end # #call
         
     | 
| 
      
 163 
     | 
    
         
            +
              
         
     | 
| 
      
 164 
     | 
    
         
            +
              
         
     | 
| 
      
 165 
     | 
    
         
            +
            end # class Color
         
     | 
| 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative './formatters/color'
         
     |