Module: Utils::Analytics Private
- Extended by:
- Context, T::Sig
- Defined in:
- Library/Homebrew/utils/analytics.rb,
Library/Homebrew/extend/os/mac/utils/analytics.rb,
Library/Homebrew/extend/os/linux/utils/analytics.rb
Overview
This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.
Helper module for fetching and reporting analytics data.
Class Method Summary collapse
- .analytics_path ⇒ Object private
- .cask_output(cask, args:) ⇒ Object private
- .cask_path ⇒ Object private
- .clear_os_prefix_ci ⇒ Object private
- .config_delete(key) ⇒ Object private
- .config_get(key) ⇒ Object private
- .config_set(key, value) ⇒ Object private
- .config_true?(key) ⇒ Boolean private
- .custom_prefix_label ⇒ Object private
- .disable! ⇒ Object private
- .disabled? ⇒ Boolean private
- .enable! ⇒ Object private
- .format_count(count) ⇒ Object private
- .format_percent(percent) ⇒ Object private
- .formula_output(f, args:) ⇒ Object private
- .formula_path ⇒ Object private
- .formulae_brew_sh_json(endpoint) ⇒ Object private
- .generic_analytics_path ⇒ Object private
- .generic_formula_path ⇒ Object private
- .get_analytics(json, args:) ⇒ Object private
- .messages_displayed! ⇒ Object private
- .messages_displayed? ⇒ Boolean private
- .no_message_output? ⇒ Boolean private
- .not_this_run? ⇒ Boolean private
- .os_prefix_ci ⇒ Object private
- .output(args:, filter: nil) ⇒ Object private
- .regenerate_uuid! ⇒ Object private
- .report(type, metadata = {}) ⇒ Object private
- .report_build_error(exception) ⇒ Object private
- .report_event(category, action, label = os_prefix_ci, value = nil) ⇒ Object private
- .table_output(category, days, results, os_version: false, cask_install: false) ⇒ Object private
- .uuid ⇒ Object private
Methods included from Context
current, current=, debug?, quiet?, verbose?, with_context
Class Method Details
.analytics_path ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
347 348 349 |
# File 'Library/Homebrew/utils/analytics.rb', line 347 def analytics_path "analytics" end |
.cask_output(cask, args:) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
187 188 189 190 191 192 |
# File 'Library/Homebrew/utils/analytics.rb', line 187 def cask_output(cask, args:) json = formulae_brew_sh_json("#{cask_path}/#{cask}.json") return if json.blank? || json["analytics"].blank? get_analytics(json, args: args) end |
.cask_path ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
352 353 354 |
# File 'Library/Homebrew/utils/analytics.rb', line 352 def cask_path "cask" end |
.clear_os_prefix_ci ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
198 199 200 201 202 |
# File 'Library/Homebrew/utils/analytics.rb', line 198 def clear_os_prefix_ci return unless instance_variable_defined?(:@os_prefix_ci) remove_instance_variable(:@os_prefix_ci) end |
.config_delete(key) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
316 317 318 319 320 |
# File 'Library/Homebrew/utils/analytics.rb', line 316 def config_delete(key) HOMEBREW_REPOSITORY.cd do system "git", "config", "--unset-all", "homebrew.#{key}" end end |
.config_get(key) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
304 305 306 307 308 |
# File 'Library/Homebrew/utils/analytics.rb', line 304 def config_get(key) HOMEBREW_REPOSITORY.cd do Utils.popen_read("git", "config", "--get", "homebrew.#{key}").chomp end end |
.config_set(key, value) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
310 311 312 313 314 |
# File 'Library/Homebrew/utils/analytics.rb', line 310 def config_set(key, value) HOMEBREW_REPOSITORY.cd do safe_system "git", "config", "--replace-all", "homebrew.#{key}", value.to_s end end |
.config_true?(key) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
300 301 302 |
# File 'Library/Homebrew/utils/analytics.rb', line 300 def config_true?(key) config_get(key) == "true" end |
.custom_prefix_label ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
194 195 196 |
# File 'Library/Homebrew/utils/analytics.rb', line 194 def custom_prefix_label "custom-prefix" end |
.disable! ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
115 116 117 118 |
# File 'Library/Homebrew/utils/analytics.rb', line 115 def disable! config_set(:analyticsdisabled, true) regenerate_uuid! end |
.disabled? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
86 87 88 89 90 |
# File 'Library/Homebrew/utils/analytics.rb', line 86 def disabled? return true if Homebrew::EnvConfig.no_analytics? config_true?(:analyticsdisabled) end |
.enable! ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
110 111 112 113 |
# File 'Library/Homebrew/utils/analytics.rb', line 110 def enable! config_set(:analyticsdisabled, false) end |
.format_count(count) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
334 335 336 |
# File 'Library/Homebrew/utils/analytics.rb', line 334 def format_count(count) count.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse end |
.format_percent(percent) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
338 339 340 |
# File 'Library/Homebrew/utils/analytics.rb', line 338 def format_percent(percent) format("%<percent>.2f", percent: percent) end |
.formula_output(f, args:) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
180 181 182 183 184 185 |
# File 'Library/Homebrew/utils/analytics.rb', line 180 def formula_output(f, args:) json = formulae_brew_sh_json("#{formula_path}/#{f}.json") return if json.blank? || json["analytics"].blank? get_analytics(json, args: args) end |
.formula_path ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
342 343 344 |
# File 'Library/Homebrew/utils/analytics.rb', line 342 def formula_path "formula" end |
.formulae_brew_sh_json(endpoint) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
322 323 324 325 326 327 328 329 330 331 332 |
# File 'Library/Homebrew/utils/analytics.rb', line 322 def formulae_brew_sh_json(endpoint) return if Homebrew::EnvConfig.no_analytics? || Homebrew::EnvConfig.no_github_api? output, = curl_output("--max-time", "5", "https://formulae.brew.sh/api/#{endpoint}") return if output.blank? JSON.parse(output) rescue JSON::ParserError nil end |
.generic_analytics_path ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
350 351 352 |
# File 'Library/Homebrew/utils/analytics.rb', line 350 def analytics_path "analytics" end |
.generic_formula_path ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
345 346 347 |
# File 'Library/Homebrew/utils/analytics.rb', line 345 def formula_path "formula" end |
.get_analytics(json, args:) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'Library/Homebrew/utils/analytics.rb', line 155 def get_analytics(json, args:) full_analytics = args.analytics? || verbose? ohai "Analytics" json["analytics"].each do |category, value| category = category.tr("_", "-") analytics = [] value.each do |days, results| days = days.to_i if full_analytics next if args.days.present? && args.days&.to_i != days next if args.category.present? && args.category != category table_output(category, days, results) else total_count = results.values.inject("+") analytics << "#{number_readable(total_count)} (#{days} days)" end end puts "#{category}: #{analytics.join(", ")}" unless full_analytics end end |
.messages_displayed! ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
105 106 107 108 |
# File 'Library/Homebrew/utils/analytics.rb', line 105 def config_set(:analyticsmessage, true) config_set(:caskanalyticsmessage, true) end |
.messages_displayed? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
82 83 84 |
# File 'Library/Homebrew/utils/analytics.rb', line 82 def config_true?(:analyticsmessage) && config_true?(:caskanalyticsmessage) end |
.no_message_output? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
96 97 98 99 |
# File 'Library/Homebrew/utils/analytics.rb', line 96 def # Used by Homebrew/install ENV["HOMEBREW_NO_ANALYTICS_MESSAGE_OUTPUT"].present? end |
.not_this_run? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
92 93 94 |
# File 'Library/Homebrew/utils/analytics.rb', line 92 def not_this_run? ENV["HOMEBREW_NO_ANALYTICS_THIS_RUN"].present? end |
.os_prefix_ci ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
204 205 206 207 208 209 210 211 |
# File 'Library/Homebrew/utils/analytics.rb', line 204 def os_prefix_ci @os_prefix_ci ||= begin os = OS_VERSION prefix = ", #{custom_prefix_label}" unless Homebrew.default_prefix? ci = ", CI" if ENV["CI"] "#{os}#{prefix}#{ci}" end end |
.output(args:, filter: nil) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'Library/Homebrew/utils/analytics.rb', line 125 def output(args:, filter: nil) days = args.days || "30" category = args.category || "install" json = formulae_brew_sh_json("analytics/#{category}/#{days}d.json") return if json.blank? || json["items"].blank? os_version = category == "os-version" cask_install = category == "cask-install" results = {} json["items"].each do |item| key = if os_version item["os_version"] elsif cask_install item["cask"] else item["formula"] end next if filter.present? && key != filter && !key.start_with?("#{filter} ") results[key] = item["count"].tr(",", "").to_i end if filter.present? && results.blank? onoe "No results matching `#{filter}` found!" return end table_output(category, days, results, os_version: os_version, cask_install: cask_install) end |
.regenerate_uuid! ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
120 121 122 123 |
# File 'Library/Homebrew/utils/analytics.rb', line 120 def regenerate_uuid! # it will be regenerated in next run unless disabled. config_delete(:analyticsuuid) end |
.report(type, metadata = {}) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'Library/Homebrew/utils/analytics.rb', line 14 def report(type, = {}) return if not_this_run? return if disabled? args = [] # do not load .curlrc unless requested (must be the first argument) args << "--disable" unless Homebrew::EnvConfig.curlrc? args += %W[ --max-time 3 --user-agent #{HOMEBREW_USER_AGENT_CURL} --data v=1 --data aip=1 --data t=#{type} --data tid=#{ENV["HOMEBREW_ANALYTICS_ID"]} --data cid=#{ENV["HOMEBREW_ANALYTICS_USER_UUID"]} --data an=#{HOMEBREW_PRODUCT} --data av=#{HOMEBREW_VERSION} ] .each do |key, value| next unless key next unless value key = ERB::Util.url_encode key value = ERB::Util.url_encode value args << "--data" << "#{key}=#{value}" end # Send analytics. Don't send or store any personally identifiable information. # https://docs.brew.sh/Analytics # https://developers.google.com/analytics/devguides/collection/protocol/v1/devguide # https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters if ENV["HOMEBREW_ANALYTICS_DEBUG"] url = "https://www.google-analytics.com/debug/collect" puts "#{ENV["HOMEBREW_CURL"]} #{args.join(" ")} #{url}" puts Utils.popen_read ENV["HOMEBREW_CURL"], *args, url else pid = fork do exec ENV["HOMEBREW_CURL"], *args, "--silent", "--output", "/dev/null", "https://www.google-analytics.com/collect" end Process.detach pid end end |
.report_build_error(exception) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
70 71 72 73 74 75 76 77 78 79 80 |
# File 'Library/Homebrew/utils/analytics.rb', line 70 def report_build_error(exception) return unless exception.formula.tap return unless exception.formula.tap.installed? return if exception.formula.tap.private? action = exception.formula.full_name if ( = exception..to_a.map(&:to_s).join(" ").presence) action = "#{action} #{}".strip end report_event("BuildError", action) end |
.report_event(category, action, label = os_prefix_ci, value = nil) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
62 63 64 65 66 67 68 |
# File 'Library/Homebrew/utils/analytics.rb', line 62 def report_event(category, action, label = os_prefix_ci, value = nil) report(:event, ec: category, ea: action, el: label, ev: value) end |
.table_output(category, days, results, os_version: false, cask_install: false) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 |
# File 'Library/Homebrew/utils/analytics.rb', line 213 def table_output(category, days, results, os_version: false, cask_install: false) oh1 "#{category} (#{days} days)" total_count = results.values.inject("+") formatted_total_count = format_count(total_count) formatted_total_percent = format_percent(100) index_header = "Index" count_header = "Count" percent_header = "Percent" = if os_version "macOS Version" elsif cask_install "Token" else "Name (with options)" end = "Total" max_index_width = results.length.to_s.length index_width = [ index_header.length, .length, max_index_width, ].max count_width = [ count_header.length, formatted_total_count.length, ].max percent_width = [ percent_header.length, formatted_total_percent.length, ].max = Tty.width - index_width - count_width - percent_width - 10 # spacing and lines formatted_index_header = format "%#{index_width}s", index_header = format "%-#{}s", [0..-1] formatted_count_header = format "%#{count_width}s", count_header formatted_percent_header = format "%#{percent_width}s", percent_header puts "#{formatted_index_header} | #{} | "\ "#{formatted_count_header} | #{formatted_percent_header}" columns_line = "#{"-"*index_width}:|-#{"-"*}-|-"\ "#{"-"*count_width}:|-#{"-"*percent_width}:" puts columns_line index = 0 results.each do |, count| index += 1 formatted_index = format "%0#{max_index_width}d", index formatted_index = format "%-#{index_width}s", formatted_index = format "%-#{}s", [0..-1] formatted_count = format "%#{count_width}s", format_count(count) formatted_percent = if total_count.zero? format "%#{percent_width}s", format_percent(0) else format "%#{percent_width}s", format_percent((count.to_i * 100) / total_count.to_f) end puts "#{formatted_index} | #{} | " \ "#{formatted_count} | #{formatted_percent}%" next if index > 10 end return unless results.length > 1 = format "%-#{index_width}s", = format "%-#{}s", "" = format "%#{count_width}s", formatted_total_count = format "%#{percent_width}s", formatted_total_percent puts "#{} | #{} | "\ "#{} | #{}%" end |
.uuid ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
101 102 103 |
# File 'Library/Homebrew/utils/analytics.rb', line 101 def uuid config_get(:analyticsuuid) end |