Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/appeals 22218 #19366

Merged
merged 54 commits into from
Sep 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
6269627
Add error handling to GET requests (#18679)
zurbergram Jun 7, 2023
6a9fbed
Merge branch 'master' into feature/APPEALS-22218
zurbergram Jun 7, 2023
cb99274
rubocop fixes
zurbergram Jun 7, 2023
0fc6388
Update metrics_service.rb
zurbergram Jun 7, 2023
fef4d9f
only show metrics for past hour and only in demo
zurbergram Jun 7, 2023
5aa705d
disable interface_version_2 for all
zurbergram Jun 8, 2023
c091c0e
scrollbar on top
zurbergram Jun 8, 2023
2c86f38
display css_id for metrics dashboard
zurbergram Jun 8, 2023
e7e8226
Update show.html.erb
zurbergram Jun 8, 2023
d94efd2
include start and end for MetricsService metrics
zurbergram Jun 8, 2023
9cc5cef
Update show.html.erb
zurbergram Jun 8, 2023
2b48fd4
Update show.html.erb
zurbergram Jun 8, 2023
13ba3bf
enable metric capture for all ApiUtil errors
zurbergram Jun 8, 2023
06cfd45
revert change
zurbergram Jun 8, 2023
8476091
fix metric recording
zurbergram Jun 9, 2023
6a2ec3e
Improved frontend metrics capturing (#18742)
zurbergram Jun 12, 2023
6232916
add metricsLoadScreen feature toggle
zurbergram Jun 12, 2023
bde0133
Update DecisionReviewer.jsx
zurbergram Jun 12, 2023
1ed422f
Merge branch 'master' of https://github.com/department-of-veterans-af…
zurbergram Jun 14, 2023
06a5f15
Mbeard/appeals 23486 (#18781)
mbeardy Jun 16, 2023
3f26b3b
APPEALS-23487: Add additional metrics for Browser captured error (#18…
kshiflett88 Jun 16, 2023
bd5f764
APPEALS-23475. Record Successhandling in the metrics (#18774)
SHarshain Jun 20, 2023
c036bbc
Aedara/appeals 23485 (#18809)
AnandEdara Jun 21, 2023
a835dcb
Cmartine/appeals 23480 (#18812)
Chris-Martine Jun 22, 2023
297db5c
APPEALS-23487 - Add Browser Error Metrics (#18824)
kshiflett88 Jun 22, 2023
d31b11c
Merge branch 'master' of https://github.com/department-of-veterans-af…
zurbergram Jun 22, 2023
2d902f6
Chrisbdetlef/appeals 23479 (#18842)
cdetlefva Jun 22, 2023
75a0bfa
Merge branch 'master' of https://github.com/department-of-veterans-af…
zurbergram Jun 23, 2023
581e70b
Update index.html.erb
zurbergram Jun 23, 2023
cd95da0
Merge branch 'master' of https://github.com/department-of-veterans-af…
zurbergram Jun 27, 2023
8e87adb
Add feature toggle to enable all metrics at once (#18902)
zurbergram Jun 29, 2023
3d594a1
add additional storeMetrics for error catches and cleanup code
zurbergram Jun 30, 2023
127cb40
Update schema.rb
zurbergram Jun 30, 2023
a268274
revert changes to client/app/2.0/screens/reader/DocumentViewer.jsx
zurbergram Jun 30, 2023
dd7e8b9
Merge branch 'master' of https://github.com/department-of-veterans-af…
zurbergram Jun 30, 2023
f9ee6d5
Merge branch 'master' into feature/APPEALS-22218
zurbergram Jul 6, 2023
5ed9e0d
Updated the cache to return (#18971)
SHarshain Jul 10, 2023
1b86e94
Merge branch 'master' of https://github.com/department-of-veterans-af…
zurbergram Jul 10, 2023
e7c0e49
Merge branch 'master' into feature/APPEALS-22218-master
mikefinneran Aug 3, 2023
0c9d22a
Merge pull request #19129 from department-of-veterans-affairs/feature…
mikefinneran Aug 3, 2023
1c22bcd
added newrelic ignore helper (#19027)
SHarshain Aug 10, 2023
5ca8f84
Merge conflict fix 08 14 2023 (#19185)
SHarshain Aug 14, 2023
37c8831
Merge branch 'master' into feature/APPEALS-22218
mikefinneran Aug 22, 2023
cb9dc6d
Add Sentry error capturing for logs controller (#19034)
Chris-Martine Aug 25, 2023
d0bbb67
Add Sentry error capturing for logs controller (#19271)
mikefinneran Aug 25, 2023
bb20572
update caseflow commons gem to original version used on master
mikefinneran Aug 29, 2023
c7cc0a9
APPEALS-26109: Metric Service Sentry Updates (#19316)
mikefinneran Aug 30, 2023
d676462
Merge branch 'master' into feature/APPEALS-22218
mikefinneran Sep 6, 2023
56324ee
remove new relic mention
mikefinneran Sep 6, 2023
91a52d7
remove new relic mention
mikefinneran Sep 6, 2023
dc9c17e
add feature flag for user metrics being enabled
mikefinneran Sep 6, 2023
aca620c
Merge remote-tracking branch 'origin/master' into feature/APPEALS-22218
ThorntonMatthew Sep 6, 2023
409d588
Merge branch 'master' into feature/APPEALS-22218
mikefinneran Sep 6, 2023
e20ceeb
Merge branch 'feature/APPEALS-22218' of github.com:department-of-vete…
mikefinneran Sep 6, 2023
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
3 changes: 2 additions & 1 deletion app/controllers/help_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ class HelpController < ApplicationController

def feature_toggle_ui_hash(user = current_user)
{
programOfficeTeamManagement: FeatureToggle.enabled?(:program_office_team_management, user: user)
programOfficeTeamManagement: FeatureToggle.enabled?(:program_office_team_management, user: user),
metricsBrowserError: FeatureToggle.enabled?(:metrics_browser_error, user: current_user)
}
end

Expand Down
3 changes: 2 additions & 1 deletion app/controllers/intakes_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ def feature_toggle_ui_hash
eduPreDocketAppeals: FeatureToggle.enabled?(:edu_predocket_appeals, user: current_user),
updatedAppealForm: FeatureToggle.enabled?(:updated_appeal_form, user: current_user),
hlrScUnrecognizedClaimants: FeatureToggle.enabled?(:hlr_sc_unrecognized_claimants, user: current_user),
vhaClaimReviewEstablishment: FeatureToggle.enabled?(:vha_claim_review_establishment, user: current_user)
vhaClaimReviewEstablishment: FeatureToggle.enabled?(:vha_claim_review_establishment, user: current_user),
metricsBrowserError: FeatureToggle.enabled?(:metrics_browser_error, user: current_user)
}
end

Expand Down
24 changes: 24 additions & 0 deletions app/controllers/metrics/dashboard_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

class Metrics::DashboardController < ApplicationController
before_action :require_demo

def show
no_cache

@metrics = Metric.includes(:user).where("created_at > ?", 1.hour.ago).order(created_at: :desc)

begin
render :show, layout: "plain_application"
rescue StandardError => error
Rails.logger.error(error.full_message)
raise error.full_message
end
end

private

def require_demo
redirect_to "/unauthorized" unless Rails.deploy_env?(:demo)
end
end
44 changes: 44 additions & 0 deletions app/controllers/metrics/v2/logs_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# frozen_string_literal: true

class Metrics::V2::LogsController < ApplicationController
skip_before_action :verify_authentication

def create
metric = Metric.create_metric_from_rest(self, allowed_params, current_user)
failed_metric_info = metric&.errors.inspect || allowed_params[:message]
Rails.logger.info("Failed to create metric #{failed_metric_info}") unless metric&.valid?

if (metric.metric_type === 'error')
error_info = {
name: metric.metric_name,
class: metric.metric_class,
attrs: metric.metric_attributes,
created_at: metric.created_at,
uuid: metric.uuid,
}
error = StandardError.new(error_info)
Raven.capture_exception(error)
end

head :ok
end

def allowed_params
params.require(:metric).permit(:uuid,
:name,
:group,
:message,
:type,
:product,
:app_name,
:metric_attributes,
:additional_info,
:sent_to,
:sent_to_info,
:relevant_tables_info,
:start,
:end,
:duration
)
end
end
3 changes: 2 additions & 1 deletion app/controllers/test/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ class Test::UsersController < ApplicationController
stats: "/stats",
jobs: "/jobs",
admin: "/admin",
test_veterans: "/test/data"
test_veterans: "/test/data",
metrics_dashboard: "/metrics/dashboard"
}
}
].freeze
Expand Down
1 change: 0 additions & 1 deletion app/jobs/update_appellant_representation_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ class UpdateAppellantRepresentationJob < CaseflowJob
include ActionView::Helpers::DateHelper
queue_with_priority :low_priority
application_attr :queue

APP_NAME = "caseflow_job"
METRIC_GROUP_NAME = UpdateAppellantRepresentationJob.name.underscore
TOTAL_NUMBER_OF_APPEALS_TO_UPDATE = 1000
Expand Down
105 changes: 105 additions & 0 deletions app/models/metric.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# frozen_string_literal: true

class Metric < CaseflowRecord
belongs_to :user

METRIC_TYPES = { error: "error", log: "log", performance: "performance", info: "info" }.freeze
LOG_SYSTEMS = { datadog: "datadog", rails_console: "rails_console", javascript_console: "javascript_console" }
PRODUCT_TYPES = {
queue: "queue",
hearings: "hearings",
intake: "intake",
vha: "vha",
efolder: "efolder",
reader: "reader",
caseflow: "caseflow", # Default product
# Added below because MetricService has usages of this as a service
vacols: "vacols",
bgs: "bgs",
gov_delivery: "gov_delivery",
mpi: "mpi",
pexip: "pexip",
va_dot_gov: "va_dot_gov",
va_notify: "va_notify",
vbms: "vbms",
}.freeze
APP_NAMES = { caseflow: "caseflow", efolder: "efolder" }.freeze
METRIC_GROUPS = { service: "service" }.freeze

validates :metric_type, inclusion: { in: METRIC_TYPES.values }
validates :metric_product, inclusion: { in: PRODUCT_TYPES.values }
validates :metric_group, inclusion: { in: METRIC_GROUPS.values }
validates :app_name, inclusion: { in: APP_NAMES.values }
validate :sent_to_in_log_systems

def self.create_metric(klass, params, user)
create(default_object(klass, params, user))
end

def self.create_metric_from_rest(klass, params, user)
params[:metric_attributes] = JSON.parse(params[:metric_attributes]) if params[:metric_attributes]
params[:additional_info] = JSON.parse(params[:additional_info]) if params[:additional_info]
params[:sent_to_info] = JSON.parse(params[:sent_to_info]) if params[:sent_to_info]
params[:relevant_tables_info] = JSON.parse(params[:relevant_tables_info]) if params[:relevant_tables_info]

create(default_object(klass, params, user))
end

def sent_to_in_log_systems
invalid_systems = sent_to - LOG_SYSTEMS.values
msg = "contains invalid log systems. The following are valid log systems #{LOG_SYSTEMS.values}"
errors.add(:sent_to, msg) if !invalid_systems.empty?
end

def css_id
user.css_id
end

private

# Returns an object with defaults set if below symbols are not found in params default object.
# Looks for these symbols in params parameter
# - uuid
# - name
# - group
# - message
# - type
# - product
# - app_name
# - metric_attributes
# - additional_info
# - sent_to
# - sent_to_info
# - relevant_tables_info
# - start
# - end
# - duration
def self.default_object(klass, params, user)
{
uuid: params[:uuid],
user: user || User.new(full_name: "Stand in user for testing", css_id: SecureRandom.uuid, station_id: 'Metrics'),
metric_name: params[:name] || METRIC_TYPES[:log],
metric_class: klass&.try(:name) || klass&.class.name || self.name,
metric_group: params[:group] || METRIC_GROUPS[:service],
metric_message: params[:message] || METRIC_TYPES[:log],
metric_type: params[:type] || METRIC_TYPES[:log],
metric_product: PRODUCT_TYPES[params[:product]] || PRODUCT_TYPES[:caseflow],
app_name: params[:app_name] || APP_NAMES[:caseflow],
metric_attributes: params[:metric_attributes],
additional_info: params[:additional_info],
sent_to: Array(params[:sent_to]).flatten,
sent_to_info: params[:sent_to_info],
relevant_tables_info: params[:relevant_tables_info],
start: params[:start],
end: params[:end],
duration: calculate_duration(params[:start], params[:end], params[:duration]),
}
end

def self.calculate_duration(start, end_time, duration)
return duration if duration || !start || !end_time

end_time - start
end

end
86 changes: 80 additions & 6 deletions app/services/metrics_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,86 @@

# see https://dropwizard.github.io/metrics/3.1.0/getting-started/ for abstractions on metric types
class MetricsService
def self.record(description, service: nil, name: "unknown")
def self.record(description, service: nil, name: "unknown", caller: nil)
return nil unless FeatureToggle.enabled?(:metrics_monitoring, user: current_user)

return_value = nil
app = RequestStore[:application] || "other"
service ||= app
uuid = SecureRandom.uuid
metric_name= 'request_latency'
sent_to = [[Metric::LOG_SYSTEMS[:rails_console]]]
sent_to_info = nil

start = Time.now
Rails.logger.info("STARTED #{description}")
stopwatch = Benchmark.measure do
return_value = yield
end
stopped = Time.now

if service
latency = stopwatch.real
DataDogService.emit_gauge(
sent_to_info = {
metric_group: "service",
metric_name: "request_latency",
metric_name: metric_name,
metric_value: latency,
app_name: app,
attrs: {
service: service,
endpoint: name
endpoint: name,
uuid: uuid
}
)
}
DataDogService.emit_gauge(sent_to_info)

sent_to << Metric::LOG_SYSTEMS[:datadog]
end

Rails.logger.info("FINISHED #{description}: #{stopwatch}")

metric_params = {
name: metric_name,
message: description,
type: Metric::METRIC_TYPES[:performance],
product: service,
attrs: {
service: service,
endpoint: name
},
sent_to: sent_to,
sent_to_info: sent_to_info,
start: start,
end: stopped,
duration: stopwatch.total * 1000 # values is in seconds and we want milliseconds
}
store_record_metric(uuid, metric_params, caller)

return_value
rescue StandardError
rescue StandardError => error
Rails.logger.error("#{error.message}\n#{error.backtrace.join("\n")}")
Raven.capture_exception(error, extra: { type: "request_error", service: service, name: name, app: app })

increment_datadog_counter("request_error", service, name, app) if service

metric_params = {
name: "Stand in object if metrics_service.record fails",
message: "Variables not initialized before failure",
type: Metric::METRIC_TYPES[:error],
product: "",
attrs: {
service: "",
endpoint: ""
},
sent_to: [[Metric::LOG_SYSTEMS[:rails_console]]],
sent_to_info: "",
start: 'Time not recorded',
end: 'Time not recorded',
duration: 'Time not recorded'
}

store_record_metric(uuid, metric_params, caller)

# Re-raise the same error. We don't want to interfere at all in normal error handling.
# This is just to capture the metric.
raise
Expand All @@ -51,4 +102,27 @@ def self.record(description, service: nil, name: "unknown")
}
)
end

private

def self.store_record_metric(uuid, params, caller)

name ="caseflow.server.metric.#{params[:name]&.downcase.gsub(/::/, '.')}"
params = {
uuid: uuid,
name: name,
message: params[:message],
type: params[:type],
product: params[:product],
metric_attributes: params[:attrs],
sent_to: params[:sent_to],
sent_to_info: params[:sent_to_info],
start: params[:start],
end: params[:end],
duration: params[:duration],
}
metric = Metric.create_metric(caller || self, params, RequestStore[:current_user])
failed_metric_info = metric&.errors.inspect
Rails.logger.info("Failed to create metric #{failed_metric_info}") unless metric&.valid?
end
end
5 changes: 4 additions & 1 deletion app/views/certifications/v2.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
dropdownUrls: dropdown_urls,
feedbackUrl: feedback_url,
buildDate: build_date,
vacolsId: @certification.vacols_id
vacolsId: @certification.vacols_id,
featureToggles: {
metricsBrowserError: FeatureToggle.enabled?(:metrics_browser_error, user: current_user)
}
}) %>
<% end %>
3 changes: 2 additions & 1 deletion app/views/decision_reviews/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
businessLine: business_line.name,
businessLineUrl: business_line.url,
featureToggles: {
decisionReviewQueueSsnColumn: FeatureToggle.enabled?(:decision_review_queue_ssn_column, user: current_user)
decisionReviewQueueSsnColumn: FeatureToggle.enabled?(:decision_review_queue_ssn_column, user: current_user),
metricsBrowserError: FeatureToggle.enabled?(:metrics_browser_error, user: current_user)
},
baseTasksUrl: business_line.tasks_url,
taskFilterDetails: task_filter_details
Expand Down
7 changes: 5 additions & 2 deletions app/views/dispatch/establish_claims/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
buildDate: build_date,
buttonText: start_text,
userQuota: user_quota && user_quota.to_hash,
currentUserHistoricalTasks: current_user_historical_tasks.map(&:to_hash)
currentUserHistoricalTasks: current_user_historical_tasks.map(&:to_hash),
featureToggles: {
metricsBrowserError: FeatureToggle.enabled?(:metrics_browser_error, user: current_user)
}
}) %>
<% end %>
<% end %>
5 changes: 4 additions & 1 deletion app/views/hearings/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
userIsDvc: current_user.can_view_judge_team_management?,
userIsHearingManagement: current_user.in_hearing_management_team?,
userIsBoardAttorney: current_user.attorney?,
userIsHearingAdmin: current_user.in_hearing_admin_team?
userIsHearingAdmin: current_user.in_hearing_admin_team?,
featureToggles: {
metricsBrowserError: FeatureToggle.enabled?(:metrics_browser_error, user: current_user)
}
}) %>
<% end %>
3 changes: 3 additions & 0 deletions app/views/inbox/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
inbox: {
messages: messages,
pagination: pagination
},
featureToggles: {
metricsBrowserError: FeatureToggle.enabled?(:metrics_browser_error, user: current_user)
}
}) %>
<% end %>
3 changes: 3 additions & 0 deletions app/views/intake_manager/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@
dropdownUrls: dropdown_urls,
feedbackUrl: feedback_url,
buildDate: build_date
featureToggles: {
metricsBrowserError: FeatureToggle.enabled?(:metrics_browser_error, user: current_user)
}
}) %>
<% end %>
Loading
Loading