modularization_statistics 1.43.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f62a7a832093f586bea43e63af693a848f52cf0e4528348746424d4a80c10d12
4
- data.tar.gz: a7d15eff1dc8014fd5552372081d6a171dff2625dade956b6ef0554e45631c3f
3
+ metadata.gz: b4b5268e6966983f8e8195225a5450391bb6ccf5b993d939b03d317b4523ef52
4
+ data.tar.gz: 79a35f5a9cb61e4fb43a069314c282f978cbbfe1e6b71ba2e3dc7a34a6714df0
5
5
  SHA512:
6
- metadata.gz: 2b510bef418709597c3c215d24752de7db71f411765517c350cfc4e8ebf5e396ecb7399ab340defbdc8bb6538e38cdb713f2d209407c5ced0ed4ff0a17f9b04a
7
- data.tar.gz: 3dc87181542fcb8bcb37561d9aa12df9ebe152f397da7c5f01c3b5b579c048102e9640929d1d6e6d3d806d6bbf5386524b411d2679324bf483e335d8b8065730
6
+ metadata.gz: 04fce30c1cefb4aac8265695b0ad7814842cea6138390223f634010f7869a98952b0f08a3bc065a9a4141e810a930f2ce62bf32c9445ae34a0d10f2e5e347c0b
7
+ data.tar.gz: 344d3b87d0ac22538f9ff72e053fc4bfdde5cb7857867d8a6e68254ce485a889f9c4f9a78a16e94f588b718cd66e2cae814bab7a77eefee0555d1ea34582668e
@@ -25,9 +25,6 @@ module ModularizationStatistics
25
25
  all_metrics << GaugeMetric.for('all_packages.enforcing_dependencies.count', packages.count(&:enforces_dependencies?), package_tags)
26
26
  all_metrics << GaugeMetric.for('all_packages.enforcing_privacy.count', packages.count(&:enforces_privacy?), package_tags)
27
27
 
28
- all_metrics << GaugeMetric.for('all_packages.notify_on_package_yml_changes.count', packages.count { |p| p.metadata['notify_on_package_yml_changes'] }, package_tags)
29
- all_metrics << GaugeMetric.for('all_packages.notify_on_new_violations.count', packages.count { |p| p.metadata['notify_on_new_violations'] }, package_tags)
30
-
31
28
  all_metrics << GaugeMetric.for('all_packages.with_violations.count', packages.count { |package| package.violations.any? }, package_tags)
32
29
  all_metrics += Metrics::PublicUsage.get_public_usage_metrics('all_packages', packages, package_tags)
33
30
  all_metrics << GaugeMetric.for('all_packages.has_readme.count', packages.count { |package| Metrics.has_readme?(package) }, package_tags)
@@ -24,11 +24,8 @@ module ModularizationStatistics
24
24
  team_tags = Metrics.tags_for_team(team_name) + [app_level_tag]
25
25
  all_metrics << GaugeMetric.for('by_team.all_packages.count', packages_by_team.count, team_tags)
26
26
  all_metrics += Metrics::PackwerkCheckerUsage.get_checker_metrics('by_team', packages_by_team, team_tags)
27
+ all_metrics += Metrics::RubocopUsage.get_metrics('by_team', packages_by_team, team_tags)
27
28
  all_metrics += Metrics::PublicUsage.get_public_usage_metrics('by_team', packages_by_team, team_tags)
28
-
29
- all_metrics << GaugeMetric.for('by_team.notify_on_package_yml_changes.count', packages_by_team.count { |p| p.metadata['notify_on_package_yml_changes'] }, team_tags)
30
- all_metrics << GaugeMetric.for('by_team.notify_on_new_violations.count', packages_by_team.count { |p| p.metadata['notify_on_new_violations'] }, team_tags)
31
-
32
29
  #
33
30
  # VIOLATIONS (implicit dependencies)
34
31
  #
@@ -13,11 +13,6 @@ module ModularizationStatistics
13
13
  class PackwerkChecker < T::Struct
14
14
  const :setting, String
15
15
  const :strict_mode, String
16
- # Later, we might convert to legacy metric names later so new clients get more sensible metric names
17
- # That is, we might want to see metrics that are more closely connected to the new API.
18
- # e.g. instead of `all_packages.prevent_this_package_from_violating_its_stated_dependencies.fail_on_any.count`, we'd see `all_packages.checkers.enforce_dependencies.strict.count`
19
- # e.g. instead of `all_packages.prevent_this_package_from_creating_other_namespaces.fail_on_new.count`, `all_packages.cops.packs_namespaceconvention.true.count`
20
- const :legacy_metric_name, String
21
16
  end
22
17
 
23
18
  sig { params(prefix: String, packages: T::Array[ParsePackwerk::Package], package_tags: T::Array[Tag]).returns(T::Array[GaugeMetric]) }
@@ -25,26 +20,26 @@ module ModularizationStatistics
25
20
  metrics = T.let([], T::Array[GaugeMetric])
26
21
 
27
22
  checkers = [
28
- PackwerkChecker.new(setting: 'enforce_dependencies', strict_mode: 'enforce_dependencies_strictly', legacy_metric_name: 'prevent_this_package_from_violating_its_stated_dependencies'),
29
- PackwerkChecker.new(setting: 'enforce_privacy', strict_mode: 'enforce_privacy_strictly', legacy_metric_name: 'prevent_other_packages_from_using_this_packages_internals')
23
+ PackwerkChecker.new(setting: 'enforce_dependencies', strict_mode: 'enforce_dependencies_strictly'),
24
+ PackwerkChecker.new(setting: 'enforce_privacy', strict_mode: 'enforce_privacy_strictly')
30
25
  ]
31
26
 
32
27
  checkers.each do |checker|
33
- ['no', 'fail_the_build_if_new_instances_appear', 'fail_the_build_on_any_instances'].each do |violation_behavior|
28
+ ['false', 'true', 'strict'].each do |enabled_mode|
34
29
  count_of_packages = ParsePackwerk.all.count do |package|
35
30
  strict_mode = package.metadata[checker.strict_mode]
36
31
  enabled = YAML.load_file(package.yml)[checker.setting]
37
- case violation_behavior
38
- when 'fail_the_build_on_any_instances'
39
- !!strict_mode
40
- when 'no'
32
+ case enabled_mode
33
+ when 'false'
41
34
  !enabled
42
- when 'fail_the_build_if_new_instances_appear'
35
+ when 'true'
43
36
  enabled && !strict_mode
37
+ when 'strict'
38
+ !!strict_mode
44
39
  end
45
40
  end
46
41
 
47
- metric_name = "#{prefix}.#{checker.legacy_metric_name}.#{violation_behavior}.count"
42
+ metric_name = "#{prefix}.packwerk_checkers.#{checker.setting}.#{enabled_mode}.count"
48
43
  metrics << GaugeMetric.for(metric_name, count_of_packages, package_tags)
49
44
  end
50
45
  end
@@ -17,11 +17,10 @@ module ModularizationStatistics
17
17
 
18
18
  sig { params(prefix: String, packages: T::Array[ParsePackwerk::Package], package_tags: T::Array[Tag]).returns(T::Array[GaugeMetric]) }
19
19
  def self.get_rubocop_usage_metrics(prefix, packages, package_tags)
20
- # Rubocops
21
20
  metrics = T.let([], T::Array[GaugeMetric])
22
21
 
23
- rubocop_legacy_metric_map.each do |cop_name, legacy_name|
24
- ['no', 'fail_the_build_if_new_instances_appear', 'fail_the_build_on_any_instances'].each do |violation_behavior|
22
+ rubocops.each do |cop_name|
23
+ ['false', 'true', 'strict'].each do |enabled_mode|
25
24
  count_of_packages = ParsePackwerk.all.count do |package|
26
25
  # We will likely want a rubocop-packs API for this, to be able to ask if a cop is enabled for a pack.
27
26
  # It's possible we will want to allow these to be enabled at the top-level `.rubocop.yml`,
@@ -34,17 +33,17 @@ module ModularizationStatistics
34
33
 
35
34
  strict_mode = cop_config && cop_config['FailureMode'] == 'strict'
36
35
  enabled = cop_config && cop_config['Enabled']
37
- case violation_behavior
38
- when 'fail_the_build_on_any_instances'
39
- !!strict_mode
40
- when 'no'
36
+ case enabled_mode
37
+ when 'false'
41
38
  !enabled
42
- when 'fail_the_build_if_new_instances_appear'
39
+ when 'true'
43
40
  enabled && !strict_mode
41
+ when 'strict'
42
+ !!strict_mode
44
43
  end
45
44
  end
46
45
 
47
- metric_name = "#{prefix}.#{legacy_name}.#{violation_behavior}.count"
46
+ metric_name = "#{prefix}.rubocops.#{to_tag_name(cop_name)}.#{enabled_mode}.count"
48
47
  metrics << GaugeMetric.for(metric_name, count_of_packages, package_tags)
49
48
  end
50
49
  end
@@ -54,8 +53,8 @@ module ModularizationStatistics
54
53
 
55
54
  sig { params(prefix: String, packages: T::Array[ParsePackwerk::Package], package_tags: T::Array[Tag]).returns(T::Array[GaugeMetric]) }
56
55
  def self.get_rubocop_exclusions(prefix, packages, package_tags)
57
- rubocop_legacy_metric_map.flat_map do |cop_name, legacy_name|
58
- metric_name = "#{prefix}.#{legacy_name}.rubocop_exclusions.count"
56
+ rubocops.flat_map do |cop_name|
57
+ metric_name = "#{prefix}.rubocops.#{to_tag_name(cop_name)}.exclusions.count"
59
58
  all_exclusions_count = ParsePackwerk.all.sum { |package| exclude_count_for_package_and_protection(package, cop_name)}
60
59
  GaugeMetric.for(metric_name, all_exclusions_count, package_tags)
61
60
  end
@@ -79,14 +78,19 @@ module ModularizationStatistics
79
78
  end
80
79
  end
81
80
 
82
- sig { returns(T::Hash[String, String])}
83
- def self.rubocop_legacy_metric_map
84
- {
85
- 'Packs/ClassMethodsAsPublicApis' => 'prevent_this_package_from_exposing_an_untyped_api',
86
- 'Packs/RootNamespaceIsPackName' => 'prevent_this_package_from_creating_other_namespaces',
87
- 'Packs/TypedPublicApis' => 'prevent_this_package_from_exposing_an_untyped_api',
88
- 'Packs/DocumentedPublicApis' => 'prevent_this_package_from_exposing_undocumented_public_apis',
89
- }
81
+ sig { returns(T::Array[String])}
82
+ def self.rubocops
83
+ [
84
+ 'Packs/ClassMethodsAsPublicApis',
85
+ 'Packs/RootNamespaceIsPackName',
86
+ 'Packs/TypedPublicApis',
87
+ 'Packs/DocumentedPublicApis',
88
+ ]
89
+ end
90
+
91
+ sig { params(cop_name: String).returns(String) }
92
+ def self.to_tag_name(cop_name)
93
+ cop_name.gsub('/', '_').downcase
90
94
  end
91
95
  end
92
96
  end
@@ -2,6 +2,52 @@
2
2
 
3
3
  module ModularizationStatistics
4
4
  module Private
5
+ extend T::Sig
6
+
7
+ METRIC_REPLACEMENTS = T.let({
8
+ # enforce_dependencies
9
+ 'packwerk_checkers.enforce_dependencies.false' => 'prevent_this_package_from_violating_its_stated_dependencies.no',
10
+ 'packwerk_checkers.enforce_dependencies.true' => 'prevent_this_package_from_violating_its_stated_dependencies.fail_the_build_if_new_instances_appear',
11
+ 'packwerk_checkers.enforce_dependencies.strict' => 'prevent_this_package_from_violating_its_stated_dependencies.fail_the_build_on_any_instances',
12
+ # enforce_privacy
13
+ 'packwerk_checkers.enforce_privacy.false' => 'prevent_other_packages_from_using_this_packages_internals.no',
14
+ 'packwerk_checkers.enforce_privacy.true' => 'prevent_other_packages_from_using_this_packages_internals.fail_the_build_if_new_instances_appear',
15
+ 'packwerk_checkers.enforce_privacy.strict' => 'prevent_other_packages_from_using_this_packages_internals.fail_the_build_on_any_instances',
16
+ # Packs/TypedPublicApis
17
+ 'rubocops.packs_typedpublicapis.false' => 'prevent_this_package_from_exposing_an_untyped_api.no',
18
+ 'rubocops.packs_typedpublicapis.true' => 'prevent_this_package_from_exposing_an_untyped_api.fail_the_build_if_new_instances_appear',
19
+ 'rubocops.packs_typedpublicapis.strict' => 'prevent_this_package_from_exposing_an_untyped_api.fail_the_build_on_any_instances',
20
+ 'rubocops.packs_typedpublicapis.exclusions' => 'prevent_this_package_from_exposing_an_untyped_api.rubocop_exclusions',
21
+ # Packs/RootNamespaceIsPackName
22
+ 'rubocops.packs_rootnamespaceispackname.false' => 'prevent_this_package_from_creating_other_namespaces.no',
23
+ 'rubocops.packs_rootnamespaceispackname.true' => 'prevent_this_package_from_creating_other_namespaces.fail_the_build_if_new_instances_appear',
24
+ 'rubocops.packs_rootnamespaceispackname.strict' => 'prevent_this_package_from_creating_other_namespaces.fail_the_build_on_any_instances',
25
+ 'rubocops.packs_rootnamespaceispackname.exclusions' => 'prevent_this_package_from_creating_other_namespaces.rubocop_exclusions',
26
+ # Packs/ClassMethodsAsPublicApis
27
+ 'rubocops.packs_classmethodsaspublicapis.false' => 'prevent_this_package_from_exposing_instance_method_public_apis.no',
28
+ 'rubocops.packs_classmethodsaspublicapis.true' => 'prevent_this_package_from_exposing_instance_method_public_apis.fail_the_build_if_new_instances_appear',
29
+ 'rubocops.packs_classmethodsaspublicapis.strict' => 'prevent_this_package_from_exposing_instance_method_public_apis.fail_the_build_on_any_instances',
30
+ 'rubocops.packs_classmethodsaspublicapis.exclusions' => 'prevent_this_package_from_exposing_instance_method_public_apis.rubocop_exclusions',
31
+ # Packs/DocumentedPublicApis
32
+ 'rubocops.packs_documentedpublicapis.false' => 'prevent_this_package_from_exposing_undocumented_public_apis.no',
33
+ 'rubocops.packs_documentedpublicapis.true' => 'prevent_this_package_from_exposing_undocumented_public_apis.fail_the_build_if_new_instances_appear',
34
+ 'rubocops.packs_documentedpublicapis.strict' => 'prevent_this_package_from_exposing_undocumented_public_apis.fail_the_build_on_any_instances',
35
+ 'rubocops.packs_documentedpublicapis.exclusions' => 'prevent_this_package_from_exposing_undocumented_public_apis.rubocop_exclusions',
36
+ }, T::Hash[String, String])
37
+
38
+ sig { params(metrics: T::Array[GaugeMetric]).returns(T::Array[GaugeMetric]) }
39
+ def self.convert_metrics_to_legacy(metrics)
40
+ metrics.map do |metric|
41
+ new_metric = metric
42
+ METRIC_REPLACEMENTS.each do |current_name, legacy_name|
43
+ new_metric = new_metric.with(
44
+ name: new_metric.name.gsub(current_name, legacy_name)
45
+ )
46
+ end
47
+
48
+ new_metric
49
+ end
50
+ end
5
51
  end
6
52
 
7
53
  private_constant :Private
@@ -7,6 +7,7 @@ require 'benchmark'
7
7
  require 'code_teams'
8
8
  require 'code_ownership'
9
9
  require 'pathname'
10
+ require 'modularization_statistics/private'
10
11
  require 'modularization_statistics/private/source_code_file'
11
12
  require 'modularization_statistics/private/datadog_reporter'
12
13
  require 'parse_packwerk'
@@ -41,7 +42,9 @@ module ModularizationStatistics
41
42
  componentized_source_code_locations: T::Array[Pathname],
42
43
  packaged_source_code_locations: T::Array[Pathname],
43
44
  report_time: Time,
44
- verbose: T::Boolean
45
+ verbose: T::Boolean,
46
+ # See note on get_metrics
47
+ use_gusto_legacy_names: T::Boolean
45
48
  ).void
46
49
  end
47
50
  def self.report_to_datadog!(
@@ -51,14 +54,16 @@ module ModularizationStatistics
51
54
  componentized_source_code_locations: DEFAULT_COMPONENTIZED_SOURCE_CODE_LOCATIONS,
52
55
  packaged_source_code_locations: DEFAULT_PACKAGED_SOURCE_CODE_LOCATIONS,
53
56
  report_time: Time.now, # rubocop:disable Rails/TimeZone
54
- verbose: false
57
+ verbose: false,
58
+ use_gusto_legacy_names: false
55
59
  )
56
60
 
57
61
  all_metrics = self.get_metrics(
58
62
  source_code_pathnames: source_code_pathnames,
59
63
  componentized_source_code_locations: componentized_source_code_locations,
60
64
  packaged_source_code_locations: packaged_source_code_locations,
61
- app_name: app_name
65
+ app_name: app_name,
66
+ use_gusto_legacy_names: use_gusto_legacy_names,
62
67
  )
63
68
 
64
69
  # This helps us debug what metrics are being sent
@@ -68,6 +73,10 @@ module ModularizationStatistics
68
73
  end
69
74
  end
70
75
 
76
+ if use_gusto_legacy_names
77
+ all_metrics = Private.convert_metrics_to_legacy(all_metrics)
78
+ end
79
+
71
80
  Private::DatadogReporter.report!(
72
81
  datadog_client: datadog_client,
73
82
  report_time: report_time,
@@ -80,16 +89,22 @@ module ModularizationStatistics
80
89
  source_code_pathnames: T::Array[Pathname],
81
90
  componentized_source_code_locations: T::Array[Pathname],
82
91
  packaged_source_code_locations: T::Array[Pathname],
83
- app_name: String
92
+ app_name: String,
93
+ # It is not recommended to set this to true.
94
+ # Gusto uses this to preserve historical trends in Dashboards as the names of
95
+ # things changed, but new dashboards can use names that better match current tooling conventions.
96
+ # The behavior of setting this parameter to true might change without warning
97
+ use_gusto_legacy_names: T::Boolean
84
98
  ).returns(T::Array[GaugeMetric])
85
99
  end
86
100
  def self.get_metrics(
87
101
  source_code_pathnames:,
88
102
  componentized_source_code_locations:,
89
103
  packaged_source_code_locations:,
90
- app_name:
104
+ app_name:,
105
+ use_gusto_legacy_names: false
91
106
  )
92
- Private::DatadogReporter.get_metrics(
107
+ all_metrics = Private::DatadogReporter.get_metrics(
93
108
  source_code_files: source_code_files(
94
109
  source_code_pathnames: source_code_pathnames,
95
110
  componentized_source_code_locations: componentized_source_code_locations,
@@ -97,6 +112,12 @@ module ModularizationStatistics
97
112
  ),
98
113
  app_name: app_name
99
114
  )
115
+
116
+ if use_gusto_legacy_names
117
+ all_metrics = Private.convert_metrics_to_legacy(all_metrics)
118
+ end
119
+
120
+ all_metrics
100
121
  end
101
122
 
102
123
  sig do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: modularization_statistics
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.43.0
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gusto Engineers