Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 23 additions & 15 deletions app/jobs/reports/monthly_account_reuse_report.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,19 @@ class MonthlyAccountReuseReport < BaseReport

attr_reader :report_date

def perform(report_date)
def initialize(report_date = Time.zone.today)
@report_date = report_date
end

def perform(report_date = Time.zone.today)
@report_date = report_date

_latest, path = generate_s3_paths(REPORT_NAME, 'json', now: report_date)
body = report_body

if bucket_name.present?
upload_file_to_s3_bucket(
path: path,
body: body,
body: report_body,
content_type: 'text/csv',
bucket: bucket_name,
)
Expand Down Expand Up @@ -124,31 +127,36 @@ def total_reuse_report
def report_csv
monthly_reuse_report = total_reuse_report

csv_array = []
csv_array << ["IDV app reuse rate #{stats_month}"]
csv_array << ['Num. SPs', 'Num. users', 'Percentage']
tables_array = []
reuse_rate_table = []
reuse_rate_table << {
title: "IDV app reuse rate #{stats_month}",
float_as_percent: true,
precision: 4,
}
reuse_rate_table << ['Num. SPs', 'Num. users', 'Percentage']

monthly_reuse_report[:reuse_stats].each do |result_entry|
csv_array << [
reuse_rate_table << [
result_entry['num_agencies'],
result_entry['num_users'],
result_entry['percentage'],
]
end
csv_array << [
reuse_rate_table << [
'Total (all >1)',
monthly_reuse_report[:total_users],
monthly_reuse_report[:total_percentage],
]
tables_array << reuse_rate_table

csv_array << []
csv_array << ['Total proofed identities']
csv_array << [
"Total proofed identities (#{stats_month})",
monthly_reuse_report[:total_proofed],
]
total_proofed_identities_table = []
total_proofed_identities_table << { title: 'Total proofed identities' }
total_proofed_identities_table << ["Total proofed identities (#{stats_month})"]
total_proofed_identities_table << [monthly_reuse_report[:total_proofed]]
tables_array << total_proofed_identities_table

csv_array
tables_array
end

def report_body
Expand Down
50 changes: 50 additions & 0 deletions app/jobs/reports/monthly_key_metrics_report.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
require 'csv'

module Reports
class MonthlyKeyMetricsReport < BaseReport
REPORT_NAME = 'monthly-key-metrics-report'.freeze

attr_reader :report_date

def perform(date)
@report_date = date
csv_for_email = monthly_key_metrics_report_array
email_message = "Report: #{REPORT_NAME} #{date}"
email_addresses = emails.select(&:present?)

if !email_addresses.empty?
ReportMailer.tables_report(
email: email_addresses,
subject: "Monthly Key Metrics Report - #{date}",
message: email_message,
tables: csv_for_email,
).deliver_now
else
Rails.logger.warn 'No email addresses received - Monthly Key Metrics Report NOT SENT'
end
end

def emails
emails = [IdentityConfig.store.team_agnes_email]
if Identity::Hostdata.env == 'prod' && report_date.day == 1
emails << IdentityConfig.store.team_all_feds_email
end
emails
end

def monthly_key_metrics_report_array
csv_array = []

account_reuse_report_csv.each do |row|
csv_array << row
end

csv_array
end
Comment thread
ThatSpaceGuy marked this conversation as resolved.
Outdated

# Individual Key Metric Report
def account_reuse_report_csv
Reports::MonthlyAccountReuseReport.new(report_date).report_csv
end
end
end
6 changes: 4 additions & 2 deletions app/mailers/report_mailer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ def warn_error(email:, error:, env: Rails.env)
# each table can have a first "row" that is a hash with options
# @option opts [Boolean] :float_as_percent whether or not to render floats as percents
# @option opts [Boolean] :title title of the table
def tables_report(email:, subject:, tables:, env: Identity::Hostdata.env || 'local')
@tables = tables.each_with_index.map do |table, index|
def tables_report(email:, subject:, message:, tables:, env: Identity::Hostdata.env || 'local')
@message = message

@tables = tables.map(&:dup).each_with_index.map do |table, index|
options = table.first.is_a?(Hash) ? table.shift : {}

options[:title] ||= "Table #{index + 1}"
Expand Down
4 changes: 3 additions & 1 deletion app/views/report_mailer/tables_report.html.erb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<%#
- @message: text to put in the beginning of the email
- @tables: an array of tables, expects first "row" to be an options hash
%>
<%= @message %><br>
<% @tables.each do |table| %>
<% options, header, *rows = table %>

Expand All @@ -20,7 +22,7 @@
<% row.each do |cell| %>
<td <%= cell.is_a?(Numeric) ? 'class=table-number' : nil %> >
<% if cell.is_a?(Float) && options[:float_as_percent] %>
<%= number_to_percentage(cell * 100, precision: 2) %>
<%= number_to_percentage(cell * 100, precision: options[:precision] || 2) %>
<% else %>
<%= number_with_delimiter(cell) %>
<% end %>
Expand Down
2 changes: 2 additions & 0 deletions config/application.yml.default
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,8 @@ show_user_attribute_deprecation_warnings: false
otp_min_attempts_remaining_warning_count: 3
system_demand_report_email: 'foo@bar.com'
sp_issuer_user_counts_report_configs: '[]'
team_agnes_email: ''
team_all_feds_email: ''
team_ursula_email: ''
test_ssn_allowed_list: ''
totp_code_interval: 30
Expand Down
8 changes: 7 additions & 1 deletion config/initializers/job_configurations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -189,12 +189,18 @@
cron: cron_24h,
args: -> { [14.days.ago] },
},
# Weekly report describing account reuse
# Monthly report describing account reuse
monthly_account_reuse_report: {
class: 'Reports::MonthlyAccountReuseReport',
cron: cron_1st_of_mo,
args: -> { [Time.zone.today] },
},
# Monthly report checking in on key metrics
monthly_key_metrics_report: {
class: 'Reports::MonthlyKeyMetricsReport',
cron: cron_24h,
args: -> { [Time.zone.today] },
},
# Job to backfill encrypted_pii_recovery_multi_region on profiles
multi_region_kms_migration_profile_migration: {
class: 'MultiRegionKmsMigration::ProfileMigrationJob',
Expand Down
2 changes: 2 additions & 0 deletions lib/identity_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,8 @@ def self.build_store(config_map)
config.add(:sp_issuer_user_counts_report_configs, type: :json)
config.add(:state_tracking_enabled, type: :boolean)
config.add(:system_demand_report_email, type: :string)
config.add(:team_agnes_email, type: :string)
config.add(:team_all_feds_email, type: :string)
config.add(:team_ursula_email, type: :string)
config.add(:telephony_adapter, type: :string)
config.add(:test_ssn_allowed_list, type: :comma_separated_string_list)
Expand Down
32 changes: 19 additions & 13 deletions spec/jobs/reports/monthly_account_reuse_report_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@
require 'csv'

RSpec.describe Reports::MonthlyAccountReuseReport do
let(:report_date) { Date.new(2021, 3, 1) }

subject(:report) { Reports::MonthlyAccountReuseReport.new }

let(:report_date) { Date.new(2021, 3, 1) }
let(:s3_report_bucket_prefix) { 'reports-bucket' }
let(:s3_report_path) do
'int/monthly-account-reuse-report/2021/2021-03-01.monthly-account-reuse-report.json'
end

before do
travel_to report_date
allow(Identity::Hostdata).to receive(:env).and_return('int')
allow(Identity::Hostdata).to receive(:aws_account_id).and_return('1234')
allow(Identity::Hostdata).to receive(:aws_region).and_return('us-west-1')
Expand All @@ -28,14 +30,14 @@
it 'uploads a file to S3 based on the report date' do
expect(report).to receive(:upload_file_to_s3_bucket).with(
path: s3_report_path,
body: kind_of(String),
body: anything,
content_type: 'text/csv',
bucket: 'reports-bucket.1234-us-west-1',
).exactly(1).time.and_call_original

expect(report).to receive(:report_body).and_call_original.once

report.perform(report_date)
report.perform
end

context 'with data' do
Expand Down Expand Up @@ -122,25 +124,29 @@ def create_identity(id, provider, verified_time)
it 'aggregates by issuer' do
expect(report).to receive(:upload_file_to_s3_bucket).
exactly(1).times do |path:, body:, content_type:, bucket:|
actual_csv = body # CSV.parse(body, headers: true)
actual_csv = body
expected_csv = CSV.generate do |csv|
[
['IDV app reuse rate Feb-2021'],
['Num. SPs', 'Num. users', 'Percentage'],
[2, 3, 30.0],
[3, 2, 20.0],
['Total (all >1)', 5, 50.0],
[],
['Total proofed identities'],
['Total proofed identities (Feb-2021)', 10],
[
{ title: 'IDV app reuse rate Feb-2021', float_as_percent: true, precision: 4 },
['Num. SPs', 'Num. users', 'Percentage'],
[2, 3, 30.0],
[3, 2, 20.0],
['Total (all >1)', 5, 50.0],
],
[
{ title: 'Total proofed identities' },
['Total proofed identities (Feb-2021)'],
[10],
],
].each do |row|
csv << row
end
end
expect(actual_csv).to eq(expected_csv)
end

report.perform(report_date)
report.perform
end
end
end
Expand Down
55 changes: 55 additions & 0 deletions spec/jobs/reports/monthly_key_metrics_report_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
require 'rails_helper'

RSpec.describe Reports::MonthlyKeyMetricsReport do
subject(:report) { Reports::MonthlyKeyMetricsReport.new }

let(:report_date) { Date.new(2021, 3, 2) }
let(:name) { 'monthly-key-metrics-report' }
let(:agnes_email) { 'fake@agnes_email.com' }
let(:feds_email) { 'fake@feds_email.com' }

before do
allow(IdentityConfig.store).to receive(:team_agnes_email).
and_return(agnes_email)
allow(IdentityConfig.store).to receive(:team_all_feds_email).
and_return(feds_email)
allow(Identity::Hostdata).to receive(:env).and_return('prod')
end

it 'sends out a report to the email listed with one total user' do
expect(ReportMailer).to receive(:tables_report).once.with(
message: 'Report: monthly-key-metrics-report 2021-03-02',
email: [agnes_email],
subject: 'Monthly Key Metrics Report - 2021-03-02',
tables: anything,
).and_call_original

subject.perform(report_date)
end

it 'sends out a report to the emails listed with two users' do
first_of_month_date = report_date - 1

expect(ReportMailer).to receive(:tables_report).once.with(
message: 'Report: monthly-key-metrics-report 2021-03-01',
email: [agnes_email, feds_email],
subject: 'Monthly Key Metrics Report - 2021-03-01',
tables: anything,
).and_call_original

subject.perform(first_of_month_date)
end

it 'does not send out a report with no emails' do
allow(IdentityConfig.store).to receive(:team_agnes_email).and_return('')

expect(ReportMailer).not_to receive(:tables_report).with(
message: 'Report: monthly-key-metrics-report 2021-03-02',
email: [''],
subject: 'Monthly Key Metrics Report - 2021-03-02',
tables: anything,
).and_call_original

subject.perform(report_date)
end
end
26 changes: 26 additions & 0 deletions spec/mailers/previews/report_mailer_preview.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,36 @@ def warn_error
)
end

def monthly_key_metrics_report
ReportMailer.tables_report(
email: 'test@example.com',
subject: 'Example Key Metrics Report',
message: 'Key Metrics Report February 2021',
tables: [
[
{ title: 'IDV app reuse rate Feb-2021', float_as_percent: true, precision: 4 },
['Num. SPs', 'Num. users', 'Percentage'],
[2, 207422, 0.105164],
[3, 6700, 0.003397],
[4, 254, 0.000129],
[5, 26, 0.000013],
[6, 1, 0.000001],
['Total (all >1)', 214403, 0.108703],
],
[
{ title: 'Total proofed identities' },
['Total proofed identities (Feb-2021)'],
[1972368],
],
],
)
end

def tables_report
ReportMailer.tables_report(
email: 'test@example.com',
subject: 'Example Report',
message: 'Sample Message',
tables: [
[
['Some', 'String'],
Expand Down
1 change: 1 addition & 0 deletions spec/mailers/report_mailer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
ReportMailer.tables_report(
email: 'foo@example.com',
subject: 'My Report',
message: 'My Report - Today',
env: env,
tables: [
[
Expand Down