Skip to content

LG-7275 Expand metrics for USPS proofing attempts#6967

Merged
eileen-nava merged 8 commits intomainfrom
em/7275-proof-attempt-metrics
Sep 22, 2022
Merged

LG-7275 Expand metrics for USPS proofing attempts#6967
eileen-nava merged 8 commits intomainfrom
em/7275-proof-attempt-metrics

Conversation

@eileen-nava
Copy link
Contributor

@eileen-nava eileen-nava commented Sep 15, 2022

Resolves jira ticket #7275: Collect consistent USPS proofing attempt metrics

Summary

This PR increases the metrics that are collected during USPS proofing attempts. It includes a new method, response_analytics_attributes, which logs the below attributes during both successful and unsuccessful proofing attempts:

  • fraudSuspected
  • primaryIdType
  • secondaryIdType
  • failureReason
  • fraudSuspected
  • proofingState
  • transactionEndDateTime
  • transactionStartDateTime
  • status
  • assuranceLevel
  • proofingPostOffice
  • proofingCity
  • proofingState
  • scanCount
  • responseMessage

The above attributes will not be logged for all USPS proofing attempts that raise exceptions. For example, if there is an exception where the response is not in hash format, then these attributes won't be logged.

@eileen-nava eileen-nava force-pushed the em/7275-proof-attempt-metrics branch from ccf6192 to ea826da Compare September 16, 2022 16:37
changelog: Internal, In-person proofing, expand metrics for proofing attempts
@eileen-nava eileen-nava force-pushed the em/7275-proof-attempt-metrics branch from ea826da to dc29936 Compare September 16, 2022 18:19
@eileen-nava eileen-nava marked this pull request as ready for review September 16, 2022 18:39
@eileen-nava eileen-nava requested review from a team and NavaTim September 16, 2022 18:42
@svalexander
Copy link
Contributor

can you link the ticket in the summary?

@eileen-nava
Copy link
Contributor Author

can you link the ticket in the summary?

Thanks for noting that. I linked the ticket in the summary.

Comment on lines +299 to +322
before(:each) do
stub_request_passed_proofing_results
end
let!(:response) { stub_request_passed_proofing_results }

it_behaves_like('enrollment with a status update', passed: true, status: 'passed')

it 'logs details about the success' do
job.perform(Time.zone.now)

response_as_json = JSON.parse(response[:body])
expect(job_analytics).to have_logged_event(
'GetUspsProofingResultsJob: Enrollment status updated',
fraud_suspected: false,
reason: 'Successful status update',
fraud_suspected: response_as_json['fraudSuspected'],
primary_id_type: response_as_json['primaryIdType'],
secondary_id_type: response_as_json['secondaryIdType'],
failure_reason: response_as_json['failureReason'],
transaction_end_date_time: response_as_json['transactionEndDateTime'],
transaction_start_date_time: response_as_json['transactionStartDateTime'],
status: response_as_json['status'],
assurance_level: response_as_json['assuranceLevel'],
proofing_post_office: response_as_json['proofingPostOffice'],
proofing_city: response_as_json['proofingCity'],
proofing_state: response_as_json['proofingState'],
scan_count: response_as_json['scanCount'],
response_message: response_as_json['responseMessage'],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we move this all to the 'enrollment with a status update' shared example by doing this?

        before do
          stub_request_passed_proofing_results
        end

        it_behaves_like(
          'enrollment with a status update',
          passed: true,
          response_json: UspsInPersonProofing::Mock::Fixtures.request_passed_proofing_results_response,
          status: 'passed',
        )

And then in the shared example we could do this:

RSpec.shared_examples 'enrollment with a status update' do |passed:, status:, response_json:|
  it 'logs a message with common attributes' do
    <...omitted code...>
    response = JSON.parse(response_json)
    expect(job_analytics).to have_logged_event(
      'GetUspsProofingResultsJob: Enrollment status updated',
      assurance_level: response['assuranceLevel'],
      enrollment_code: pending_enrollment.enrollment_code,
      enrollment_id: pending_enrollment.id,
      failure_reason: response['failureReason'],
      fraud_suspected: response['fraudSuspected'],
      minutes_since_last_status_check: 15.0,
      minutes_since_last_status_update: 2.days.in_minutes,
      minutes_to_completion: 3.days.in_minutes,
      passed: passed,
      primary_id_type: response['primaryIdType'],
      proofing_city: response['proofingCity'],
      proofing_post_office: response['proofingPostOffice'],
      proofing_state: response['proofingState'],
      response_message: response['responseMessage'],
      scan_count: response['scanCount'],
      secondary_id_type: response['secondaryIdType'],
      status: response['status'],
      transaction_end_date_time: response['transactionEndDateTime'],
      transaction_start_date_time: response['transactionStartDateTime'],
    )
  end

And we could then use that shared example for most the test cases where you've added these checks. I like this approach because the shared examples already check for logged attributes and this would reduce a lot of similar looking lines of test code. And then we could revert the changes to usps_ipp_helper.rb

Comment on lines +33 to +39
fraud_suspected: response['fraudSuspected'],
primary_id_type: response['primaryIdType'],
secondary_id_type: response['secondaryIdType'],
failure_reason: response['failureReason'],
transaction_end_date_time: response['transactionEndDateTime'],
transaction_start_date_time: response['transactionStartDateTime'],
status: response['status'],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO I think all this switching of cases might be a good hint to move the processing of the response to the USPS proofer client class, have it return a Struct or equivalent object that has snake_case keys already (similar to https://cm-jira.usa.gov/browse/LG-7025)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for raising this point! I will make another ticket to address it.

@eileen-nava
Copy link
Contributor Author

Heads-up: This PR is not ready for re-review. I will post when it is. Almost there!

Comment on lines +33 to +39
fraud_suspected: response['fraudSuspected'],
primary_id_type: response['primaryIdType'],
secondary_id_type: response['secondaryIdType'],
failure_reason: response['failureReason'],
transaction_end_date_time: response['transactionEndDateTime'],
transaction_start_date_time: response['transactionStartDateTime'],
status: response['status'],
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for raising this point! I will make another ticket to address it.

end

def self.request_passed_proofing_unsupported_status_results_response
def self.request_passed_proofing_unsupported_status_response
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I shortened this method name because it set off rubocop's "line too long" check. I realize that the method name is no longer consistent with the many self.foo_results_response methods in this file. I thought about renaming those methods to self.foo_response, but decided to prioritize making the smallest change possible.

If other folks think it's worth it to refactor the self.foo_results_response methods to self.foo_response, please give a shout.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a lot of ways we can work around the Rubocop restriction, and I'd personally prefer to pursue those before choosing renaming the method, or at least when we'd be introducing inconsistency by doing so (like you mentioned).

Example:

        it_behaves_like(
          'enrollment encountering an exception',
          reason: 'Bad response structure',
          response_json: UspsInPersonProofing::Mock::Fixtures.
            request_passed_proofing_unsupported_status_result_response,
        )

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I'll take the approach you suggest.

"transactionEndDateTime": "12/17/2020 034055",
"secondaryIdType": "Deed of Trust",
"responseMessage": "More than 30 days have passed since opt-in to IPP",
"fraudSuspected": null,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed this value because I don't think we'd suspect fraud for an expired id. Also, the related method, handle_expired_status_update, has the parameter fraud_suspected: nil for the method idv_in_person_usps_proofing_results_job_enrollment_updated.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The USPS API documentation specifies that this field would only ever be true or false, so I think the fixtures should reflect the values we'd actually expect.

(Aside: Curious if these fixtures were provided to us by USPS directly. Their documentation claims the type of this field is a String of true or false, so I'm curious if that means true and false, or if it means "true" and "false". The previous fixture code would imply the former.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just checked in dev where we have some expired enrollments -- the USPS response body is this:

{"responseMessage"=>"More than 30 days have passed since opt-in to IPP"}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I'm there I checked on the value of fraud_suspected for a passed enrollment. Looks like it returns the value as a boolean:

"fraudSuspected"=>false,

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we update the expired mock response json value to match that actual response I got back @eileen-nava?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely! I'll update the expired mock response json value to match that actual response. Thanks for pointing this out, @aduth and @sheldon-b.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for checking those @sheldon-b !

@eileen-nava
Copy link
Contributor Author

This PR is ready for re-review. Thanks for everyone who provided feedback so far.

@eileen-nava
Copy link
Contributor Author

Update: I responded to the most recent round of feedback.

Copy link
Contributor

@sheldon-b sheldon-b left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Looking good. I have a few more comments, mostly minor styling things that would be nice to enforce with a linter (separate PR/ticket, not asking you to do that)

Comment on lines +2 to +15
"status": "In-person expired",
"proofingPostOffice": "WILKES BARRE",
"proofingCity": "WILKES BARRE",
"proofingState": "PA",
"enrollmentCode": "2090002197604352",
"primaryIdType": "Uniformed Services identification card",
"transactionStartDateTime": "12/17/2020 033855",
"transactionEndDateTime": "12/17/2020 034055",
"secondaryIdType": "Deed of Trust",
"responseMessage": "More than 30 days have passed since opt-in to IPP",
"fraudSuspected": false,
"proofingConfirmationNumber": "350040248346707",
"ippAssuranceLevel": "1.5"
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per this comment I suggest deleting most of these fields because USPS doesn't actually return them for expired enrollments

Suggested change
"status": "In-person expired",
"proofingPostOffice": "WILKES BARRE",
"proofingCity": "WILKES BARRE",
"proofingState": "PA",
"enrollmentCode": "2090002197604352",
"primaryIdType": "Uniformed Services identification card",
"transactionStartDateTime": "12/17/2020 033855",
"transactionEndDateTime": "12/17/2020 034055",
"secondaryIdType": "Deed of Trust",
"responseMessage": "More than 30 days have passed since opt-in to IPP",
"fraudSuspected": false,
"proofingConfirmationNumber": "350040248346707",
"ippAssuranceLevel": "1.5"
}
"responseMessage": "More than 30 days have passed since opt-in to IPP"
}

Comment on lines +47 to +62
reason: 'Request exception'|
reason: 'Request exception',
response_json: {}|
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't look like response_json is used in these shared examples. Should we revert this change?

Comment on lines +318 to +322
it_behaves_like(
'enrollment with a status update', passed: true, status: 'passed',
response_json: UspsInPersonProofing::Mock::Fixtures.
request_passed_proofing_results_response
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this style is more consistent with the rest of the codebase (and a little easier to read imo). I think I'll see if there's a rubocop rule to enforce this better in a separate PR

Similar comment for the other places below with the same styling

Suggested change
it_behaves_like(
'enrollment with a status update', passed: true, status: 'passed',
response_json: UspsInPersonProofing::Mock::Fixtures.
request_passed_proofing_results_response
)
it_behaves_like(
'enrollment with a status update',
passed: true,
status: 'passed',
response_json: UspsInPersonProofing::Mock::Fixtures.
request_passed_proofing_results_response
)

Comment on lines -328 to -335
failure_reason: 'Clerk indicates that ID name or address does not match source data.',
fraud_suspected: false,
primary_id_type: 'Uniformed Services identification card',
proofing_state: 'PA',
reason: 'Failed status',
secondary_id_type: 'Deed of Trust',
transaction_end_date_time: '12/17/2020 034055',
transaction_start_date_time: '12/17/2020 033855',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😎

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😎

@eileen-nava eileen-nava merged commit 6be4a5e into main Sep 22, 2022
@eileen-nava eileen-nava deleted the em/7275-proof-attempt-metrics branch September 22, 2022 19:55
@solipet solipet mentioned this pull request Sep 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants