From 364f1ea985844ed86b14bda00aab9a8ced4fb777 Mon Sep 17 00:00:00 2001 From: mikefinneran <110622959+mikefinneran@users.noreply.github.com> Date: Wed, 6 Sep 2023 16:49:56 -0400 Subject: [PATCH] Revert "Feature/appeals 22218" --- app/controllers/help_controller.rb | 3 +- app/controllers/intakes_controller.rb | 3 +- .../metrics/dashboard_controller.rb | 24 --- app/controllers/metrics/v2/logs_controller.rb | 44 ----- app/controllers/test/users_controller.rb | 3 +- .../update_appellant_representation_job.rb | 1 + app/models/metric.rb | 105 ------------ app/services/metrics_service.rb | 86 +--------- app/views/certifications/v2.html.erb | 5 +- app/views/decision_reviews/index.html.erb | 3 +- .../dispatch/establish_claims/index.html.erb | 7 +- app/views/hearings/index.html.erb | 5 +- app/views/inbox/index.html.erb | 3 - app/views/intake_manager/index.html.erb | 3 - app/views/metrics/dashboard/show.html.erb | 83 ---------- app/views/queue/index.html.erb | 1 - app/views/reader/appeal/index.html.erb | 7 - app/views/test/users/index.html.erb | 6 +- client/app/components/LoadingDataDisplay.jsx | 23 +-- client/app/index.js | 34 ---- client/app/reader/DecisionReviewer.jsx | 6 +- client/app/reader/DocumentSearch.jsx | 20 +-- client/app/reader/PdfFile.jsx | 35 +--- client/app/reader/PdfPage.jsx | 108 +++--------- client/app/reader/PdfUI.jsx | 2 +- client/app/reader/ReaderLoadingScreen.jsx | 6 +- client/app/util/ApiUtil.js | 154 +---------------- client/app/util/Metrics.js | 156 +----------------- client/test/app/util/ApiUtil.test.js | 61 +------ config/routes.rb | 5 - .../20230523174750_create_metrics_table.rb | 29 ---- db/schema.rb | 28 ---- .../metrics/v2/logs_controller_spec.rb | 44 ----- ...pdate_appellant_representation_job_spec.rb | 2 +- spec/models/metric_spec.rb | 50 ------ 35 files changed, 65 insertions(+), 1090 deletions(-) delete mode 100644 app/controllers/metrics/dashboard_controller.rb delete mode 100644 app/controllers/metrics/v2/logs_controller.rb delete mode 100644 app/models/metric.rb delete mode 100644 app/views/metrics/dashboard/show.html.erb delete mode 100644 db/migrate/20230523174750_create_metrics_table.rb delete mode 100644 spec/controllers/metrics/v2/logs_controller_spec.rb delete mode 100644 spec/models/metric_spec.rb diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb index b03af1f4e3d..17d7f610e3f 100644 --- a/app/controllers/help_controller.rb +++ b/app/controllers/help_controller.rb @@ -5,8 +5,7 @@ class HelpController < ApplicationController def feature_toggle_ui_hash(user = current_user) { - programOfficeTeamManagement: FeatureToggle.enabled?(:program_office_team_management, user: user), - metricsBrowserError: FeatureToggle.enabled?(:metrics_browser_error, user: current_user) + programOfficeTeamManagement: FeatureToggle.enabled?(:program_office_team_management, user: user) } end diff --git a/app/controllers/intakes_controller.rb b/app/controllers/intakes_controller.rb index 4bb2df9afea..e7401c09488 100644 --- a/app/controllers/intakes_controller.rb +++ b/app/controllers/intakes_controller.rb @@ -152,8 +152,7 @@ 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), - metricsBrowserError: FeatureToggle.enabled?(:metrics_browser_error, user: current_user) + vhaClaimReviewEstablishment: FeatureToggle.enabled?(:vha_claim_review_establishment, user: current_user) } end diff --git a/app/controllers/metrics/dashboard_controller.rb b/app/controllers/metrics/dashboard_controller.rb deleted file mode 100644 index 232aeaa9d1b..00000000000 --- a/app/controllers/metrics/dashboard_controller.rb +++ /dev/null @@ -1,24 +0,0 @@ -# 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 diff --git a/app/controllers/metrics/v2/logs_controller.rb b/app/controllers/metrics/v2/logs_controller.rb deleted file mode 100644 index 7ccdc1ec306..00000000000 --- a/app/controllers/metrics/v2/logs_controller.rb +++ /dev/null @@ -1,44 +0,0 @@ -# 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 diff --git a/app/controllers/test/users_controller.rb b/app/controllers/test/users_controller.rb index f8e5b214f4d..bf6f2d93bb8 100644 --- a/app/controllers/test/users_controller.rb +++ b/app/controllers/test/users_controller.rb @@ -62,8 +62,7 @@ class Test::UsersController < ApplicationController stats: "/stats", jobs: "/jobs", admin: "/admin", - test_veterans: "/test/data", - metrics_dashboard: "/metrics/dashboard" + test_veterans: "/test/data" } } ].freeze diff --git a/app/jobs/update_appellant_representation_job.rb b/app/jobs/update_appellant_representation_job.rb index 36ee5b65857..081741c104b 100644 --- a/app/jobs/update_appellant_representation_job.rb +++ b/app/jobs/update_appellant_representation_job.rb @@ -7,6 +7,7 @@ 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 diff --git a/app/models/metric.rb b/app/models/metric.rb deleted file mode 100644 index f28623bb62e..00000000000 --- a/app/models/metric.rb +++ /dev/null @@ -1,105 +0,0 @@ -# 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 diff --git a/app/services/metrics_service.rb b/app/services/metrics_service.rb index aa74ab6f7ed..b9b83f77df1 100644 --- a/app/services/metrics_service.rb +++ b/app/services/metrics_service.rb @@ -4,86 +4,35 @@ # 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", caller: nil) - return nil unless FeatureToggle.enabled?(:metrics_monitoring, user: current_user) - + def self.record(description, service: nil, name: "unknown") 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 - sent_to_info = { + DataDogService.emit_gauge( metric_group: "service", - metric_name: metric_name, + metric_name: "request_latency", metric_value: latency, app_name: app, attrs: { service: service, - endpoint: name, - uuid: uuid + endpoint: name } - } - 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 => 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 }) - + rescue StandardError 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 @@ -102,27 +51,4 @@ def self.record(description, service: nil, name: "unknown", caller: nil) } ) 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 diff --git a/app/views/certifications/v2.html.erb b/app/views/certifications/v2.html.erb index 8634f07ea5d..6b739da67b0 100644 --- a/app/views/certifications/v2.html.erb +++ b/app/views/certifications/v2.html.erb @@ -4,9 +4,6 @@ dropdownUrls: dropdown_urls, feedbackUrl: feedback_url, buildDate: build_date, - vacolsId: @certification.vacols_id, - featureToggles: { - metricsBrowserError: FeatureToggle.enabled?(:metrics_browser_error, user: current_user) - } + vacolsId: @certification.vacols_id }) %> <% end %> diff --git a/app/views/decision_reviews/index.html.erb b/app/views/decision_reviews/index.html.erb index e377f8dce05..548d1cdb9ad 100644 --- a/app/views/decision_reviews/index.html.erb +++ b/app/views/decision_reviews/index.html.erb @@ -10,8 +10,7 @@ businessLine: business_line.name, businessLineUrl: business_line.url, featureToggles: { - decisionReviewQueueSsnColumn: FeatureToggle.enabled?(:decision_review_queue_ssn_column, user: current_user), - metricsBrowserError: FeatureToggle.enabled?(:metrics_browser_error, user: current_user) + decisionReviewQueueSsnColumn: FeatureToggle.enabled?(:decision_review_queue_ssn_column, user: current_user) }, baseTasksUrl: business_line.tasks_url, taskFilterDetails: task_filter_details diff --git a/app/views/dispatch/establish_claims/index.html.erb b/app/views/dispatch/establish_claims/index.html.erb index 3c8c256783a..8a9cc4d7d64 100644 --- a/app/views/dispatch/establish_claims/index.html.erb +++ b/app/views/dispatch/establish_claims/index.html.erb @@ -8,9 +8,6 @@ buildDate: build_date, buttonText: start_text, userQuota: user_quota && user_quota.to_hash, - currentUserHistoricalTasks: current_user_historical_tasks.map(&:to_hash), - featureToggles: { - metricsBrowserError: FeatureToggle.enabled?(:metrics_browser_error, user: current_user) - } + currentUserHistoricalTasks: current_user_historical_tasks.map(&:to_hash) }) %> -<% end %> +<% end %> \ No newline at end of file diff --git a/app/views/hearings/index.html.erb b/app/views/hearings/index.html.erb index 55241926043..db78283f635 100644 --- a/app/views/hearings/index.html.erb +++ b/app/views/hearings/index.html.erb @@ -29,9 +29,6 @@ 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?, - featureToggles: { - metricsBrowserError: FeatureToggle.enabled?(:metrics_browser_error, user: current_user) - } + userIsHearingAdmin: current_user.in_hearing_admin_team? }) %> <% end %> diff --git a/app/views/inbox/index.html.erb b/app/views/inbox/index.html.erb index dba5d4f67ae..65ba31a93e8 100644 --- a/app/views/inbox/index.html.erb +++ b/app/views/inbox/index.html.erb @@ -8,9 +8,6 @@ inbox: { messages: messages, pagination: pagination - }, - featureToggles: { - metricsBrowserError: FeatureToggle.enabled?(:metrics_browser_error, user: current_user) } }) %> <% end %> diff --git a/app/views/intake_manager/index.html.erb b/app/views/intake_manager/index.html.erb index 9659d728be5..09ed9a2c07e 100644 --- a/app/views/intake_manager/index.html.erb +++ b/app/views/intake_manager/index.html.erb @@ -5,8 +5,5 @@ dropdownUrls: dropdown_urls, feedbackUrl: feedback_url, buildDate: build_date - featureToggles: { - metricsBrowserError: FeatureToggle.enabled?(:metrics_browser_error, user: current_user) - } }) %> <% end %> diff --git a/app/views/metrics/dashboard/show.html.erb b/app/views/metrics/dashboard/show.html.erb deleted file mode 100644 index b427d5c3290..00000000000 --- a/app/views/metrics/dashboard/show.html.erb +++ /dev/null @@ -1,83 +0,0 @@ - - - -

Metrics Dashboard

-

Shows metrics created in past hour

-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - <% @metrics.each do |metric| %> - - - - - - - - - - - - - - - - - - - - - <% end %> - -
uuidnameclassgroupmessagetypeproductappattributesadditional_infosent_tosent_to_inforelevant_tables_infostartendduration (ms)css_idcreated_at
<%= metric.uuid %><%= metric.metric_name %><%= metric.metric_class %><%= metric.metric_group %><%= metric.metric_message %><%= metric.metric_type %><%= metric.metric_product %><%= metric.app_name %><%= metric.metric_attributes %><%= metric.additional_info %><%= metric.sent_to %><%= metric.sent_to_info %><%= metric.relevant_tables_info %><%= metric.start %><%= metric.end %><%= metric.duration %><%= metric.css_id %><%= metric.created_at %>
-
-
diff --git a/app/views/queue/index.html.erb b/app/views/queue/index.html.erb index 5fa1ce56ec4..e0ba7a1038a 100644 --- a/app/views/queue/index.html.erb +++ b/app/views/queue/index.html.erb @@ -53,7 +53,6 @@ cavc_remand_granted_substitute_appellant: FeatureToggle.enabled?(:cavc_remand_granted_substitute_appellant, user: current_user), cavc_dashboard_workflow: FeatureToggle.enabled?(:cavc_dashboard_workflow, user: current_user), cc_appeal_workflow: FeatureToggle.enabled?(:cc_appeal_workflow, user: current_user), - metricsBrowserError: FeatureToggle.enabled?(:metrics_browser_error, user: current_user), cc_vacatur_visibility: FeatureToggle.enabled?(:cc_vacatur_visibility, user: current_user) } }) %> diff --git a/app/views/reader/appeal/index.html.erb b/app/views/reader/appeal/index.html.erb index 5862f351d1e..8201c415679 100644 --- a/app/views/reader/appeal/index.html.erb +++ b/app/views/reader/appeal/index.html.erb @@ -12,13 +12,6 @@ windowSlider: FeatureToggle.enabled?(:window_slider, user: current_user), readerSelectorsMemoized: FeatureToggle.enabled?(:bulk_upload_documents, user: current_user), readerGetDocumentLogging: FeatureToggle.enabled?(:reader_get_document_logging, user: current_user), - metricsLogRestError: FeatureToggle.enabled?(:metrics_log_rest_error, user: current_user), - metricsBrowserError: FeatureToggle.enabled?(:metrics_browser_error, user: current_user), - metricsLoadScreen: FeatureToggle.enabled?(:metrics_load_screen, user: current_user), - metricsRecordPDFJSGetDocument: FeatureToggle.enabled?(:metrics_get_pdfjs_doc, user: current_user), - metricsReaderRenderText: FeatureToggle.enabled?(:metrics_reader_render_text, user: current_user), - metricsLogRestSuccess: FeatureToggle.enabled?(:metrics_log_rest_success, user: current_user), - metricsPdfStorePages: FeatureToggle.enabled?(:metrics_pdf_store_pages, user: current_user), prefetchDisabled: FeatureToggle.enabled?(:prefetch_disabled, user: current_user) }, buildDate: build_date diff --git a/app/views/test/users/index.html.erb b/app/views/test/users/index.html.erb index 3bb0dff6ff5..f8a29402c45 100644 --- a/app/views/test/users/index.html.erb +++ b/app/views/test/users/index.html.erb @@ -14,10 +14,6 @@ appSelectList: Test::UsersController::APPS, userSession: user_session, timezone: { getlocal: Time.now.getlocal.zone, zone: Time.zone.name }, - epTypes: ep_types, - featureToggles: { - interfaceVersion2: FeatureToggle.enabled?(:interface_version_2, user: current_user), - metricsBrowserError: FeatureToggle.enabled?(:metrics_browser_error, user: current_user) - } + epTypes: ep_types }) %> <% end %> diff --git a/client/app/components/LoadingDataDisplay.jsx b/client/app/components/LoadingDataDisplay.jsx index f9fbb32e876..449e54a0e61 100644 --- a/client/app/components/LoadingDataDisplay.jsx +++ b/client/app/components/LoadingDataDisplay.jsx @@ -4,7 +4,6 @@ import PropTypes from 'prop-types'; import LoadingScreen from './LoadingScreen'; import StatusMessage from './StatusMessage'; import COPY from '../../COPY'; -import { recordAsyncMetrics } from '../util/Metrics'; const PROMISE_RESULTS = { SUCCESS: 'SUCCESS', @@ -43,24 +42,10 @@ class LoadingDataDisplay extends React.PureComponent { this.setState({ promiseStartTimeMs: Date.now() }); - const metricData = { - message: this.props.loadingComponentProps?.message || 'loading screen', - type: 'performance', - data: { - failStatusMessageProps: this.props.failStatusMessageProps, - loadingComponentProps: this.props.loadingComponentProps, - slowLoadMessage: this.props.slowLoadMessage, - slowLoadThresholdMs: this.props.slowLoadThresholdMs, - timeoutMs: this.props.timeoutMs - } - }; - - const shouldRecordMetrics = this.props.metricsLoadScreen; - // Promise does not give us a way to "un-then" and stop listening // when the component unmounts. So we'll leave this reference dangling, // but at least we can use this._isMounted to avoid taking action if necessary. - recordAsyncMetrics(promise, metricData, shouldRecordMetrics).then( + promise.then( () => { if (!this._isMounted) { return; @@ -177,8 +162,7 @@ LoadingDataDisplay.propTypes = { loadingComponentProps: PropTypes.object, slowLoadMessage: PropTypes.string, slowLoadThresholdMs: PropTypes.number, - timeoutMs: PropTypes.number, - metricsLoadScreen: PropTypes.bool, + timeoutMs: PropTypes.number }; LoadingDataDisplay.defaultProps = { @@ -189,8 +173,7 @@ LoadingDataDisplay.defaultProps = { errorComponent: StatusMessage, loadingComponentProps: {}, failStatusMessageProps: {}, - failStatusMessageChildren: DEFAULT_UNKNOWN_ERROR_MSG, - metricsLoadScreen: false, + failStatusMessageChildren: DEFAULT_UNKNOWN_ERROR_MSG }; export default LoadingDataDisplay; diff --git a/client/app/index.js b/client/app/index.js index 94d8d5cd734..49067c2ca5e 100644 --- a/client/app/index.js +++ b/client/app/index.js @@ -13,9 +13,6 @@ import { render } from 'react-dom'; import { forOwn } from 'lodash'; import { BrowserRouter, Switch } from 'react-router-dom'; -// Internal Dependencies -import { storeMetrics } from './util/Metrics'; - // Redux Store Dependencies import ReduxBase from 'app/components/ReduxBase'; import rootReducer from 'store/root'; @@ -58,7 +55,6 @@ import Inbox from 'app/inbox'; import Explain from 'app/explain'; import MPISearch from 'app/mpi/MPISearch'; import Admin from 'app/admin'; -import uuid from 'uuid'; const COMPONENTS = { // New Version 2.0 Root Component @@ -97,36 +93,6 @@ const COMPONENTS = { }; const componentWrapper = (component) => (props, railsContext, domNodeId) => { - window.onerror = (event, source, lineno, colno, error) => { - if (props.featureToggles?.metricsBrowserError) { - const id = uuid.v4(); - const data = { - event, - source, - lineno, - colno, - error - }; - const t0 = performance.now(); - const start = Date.now(); - const t1 = performance.now(); - const end = Date.now(); - const duration = t1 - t0; - - storeMetrics( - id, - data, - { type: 'error', - product: 'browser', - start, - end, - duration } - ); - } - - return true; - }; - /* eslint-disable */ const wrapComponent = (Component) => ( diff --git a/client/app/reader/DecisionReviewer.jsx b/client/app/reader/DecisionReviewer.jsx index 3625ad70d9a..2d676eb5e62 100644 --- a/client/app/reader/DecisionReviewer.jsx +++ b/client/app/reader/DecisionReviewer.jsx @@ -90,8 +90,7 @@ export class DecisionReviewer extends React.PureComponent { return + vacolsId={vacolsId}> + vacolsId={vacolsId}> { @@ -210,8 +198,7 @@ DocumentSearch.propTypes = { setSearchIsLoading: PropTypes.func, showSearchBar: PropTypes.func, totalMatchesInFile: PropTypes.number, - updateSearchIndex: PropTypes.func, - featureToggles: PropTypes.object, + updateSearchIndex: PropTypes.func }; const mapStateToProps = (state, props) => ({ @@ -222,8 +209,7 @@ const mapStateToProps = (state, props) => ({ currentMatchIndex: getCurrentMatchIndex(state, props), matchIndexToHighlight: state.searchActionReducer.indexToHighlight, hidden: state.pdfViewer.hideSearchBar, - textExtracted: !_.isEmpty(state.searchActionReducer.extractedText), - featureToggles: props.featureToggles, + textExtracted: !_.isEmpty(state.searchActionReducer.extractedText) }); const mapDispatchToProps = (dispatch) => ({ diff --git a/client/app/reader/PdfFile.jsx b/client/app/reader/PdfFile.jsx index 30137804c85..1941496aa7e 100644 --- a/client/app/reader/PdfFile.jsx +++ b/client/app/reader/PdfFile.jsx @@ -24,7 +24,6 @@ import { INTERACTION_TYPES } from '../reader/analytics'; import { getCurrentMatchIndex, getMatchesPerPageInFile, getSearchTerm } from './selectors'; import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.entry'; import uuid from 'uuid'; -import { storeMetrics, recordAsyncMetrics } from '../util/Metrics'; PDFJS.GlobalWorkerOptions.workerSrc = pdfjsWorker; @@ -50,9 +49,7 @@ export class PdfFile extends React.PureComponent { cache: true, withCredentials: true, timeout: true, - responseType: 'arraybuffer', - metricsLogRestError: this.props.featureToggles.metricsLogRestError, - metricsLogRestSuccess: this.props.featureToggles.metricsLogRestSuccess + responseType: 'arraybuffer' }; window.addEventListener('keydown', this.keyListener); @@ -73,20 +70,9 @@ export class PdfFile extends React.PureComponent { getDocument = (requestOptions) => { return ApiUtil.get(this.props.file, requestOptions). then((resp) => { - const metricData = { - message: `Getting PDF document id: "${this.props.documentId}"`, - type: 'performance', - product: 'reader', - data: { - file: this.props.file, - } - }; - this.loadingTask = PDFJS.getDocument({ data: resp.body }); - const promise = this.loadingTask.promise; - return recordAsyncMetrics(promise, metricData, - this.props.featureToggles.metricsRecordPDFJSGetDocument); + return this.loadingTask.promise; }, (reason) => this.onRejected(reason, 'getDocument')). then((pdfDocument) => { this.pdfDocument = pdfDocument; @@ -104,21 +90,7 @@ export class PdfFile extends React.PureComponent { return this.props.setPdfDocument(this.props.file, this.pdfDocument); }, (reason) => this.onRejected(reason, 'setPdfDocument')). catch((error) => { - const id = uuid.v4(); - const data = { - file: this.props.file - }; - const message = `${id} : GET ${this.props.file} : ${error}`; - - console.error(message); - storeMetrics( - id, - data, - { message, - type: 'error', - product: 'browser', - } - ); + console.error(`${uuid.v4()} : GET ${this.props.file} : ${error}`); this.loadingTask = null; this.props.setDocumentLoadError(this.props.file); }); @@ -245,7 +217,6 @@ export class PdfFile extends React.PureComponent { isFileVisible={this.props.isVisible} scale={this.props.scale} pdfDocument={this.props.pdfDocument} - featureToggles={this.props.featureToggles} /> ; } diff --git a/client/app/reader/PdfPage.jsx b/client/app/reader/PdfPage.jsx index 599f030d385..e4fcf0597da 100644 --- a/client/app/reader/PdfPage.jsx +++ b/client/app/reader/PdfPage.jsx @@ -1,7 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; import Mark from 'mark.js'; -import uuid, { v4 as uuidv4 } from 'uuid'; import CommentLayer from './CommentLayer'; import { connect } from 'react-redux'; @@ -13,11 +12,12 @@ import { bindActionCreators } from 'redux'; import { PDF_PAGE_HEIGHT, PDF_PAGE_WIDTH, SEARCH_BAR_HEIGHT, PAGE_DIMENSION_SCALE, PAGE_MARGIN } from './constants'; import { pageNumberOfPageIndex } from './utils'; import * as PDFJS from 'pdfjs-dist'; -import { collectHistogram, recordMetrics, recordAsyncMetrics, storeMetrics } from '../util/Metrics'; +import { collectHistogram } from '../util/Metrics'; import { css } from 'glamor'; import classNames from 'classnames'; import { COLORS } from '../constants/AppConstants'; +import uuid from 'uuid'; const markStyle = css({ '& mark': { @@ -183,7 +183,6 @@ export class PdfPage extends React.PureComponent { }; drawText = (page, text) => { - if (!this.textLayer) { return; } @@ -213,88 +212,32 @@ export class PdfPage extends React.PureComponent { setUpPage = () => { // eslint-disable-next-line no-underscore-dangle if (this.props.pdfDocument && !this.props.pdfDocument._transport.destroyed) { - const pageMetricData = { - message: 'Storing PDF page', - product: 'pdfjs.document.pages', - type: 'performance', - data: { - file: this.props.file, - documentId: this.props.documentId, - pageIndex: this.props.pageIndex, - numPagesInDoc: this.props.pdfDocument.numPages, - }, - }; + this.props.pdfDocument. + getPage(pageNumberOfPageIndex(this.props.pageIndex)). + then((page) => { + this.page = page; - const textMetricData = { - message: 'Storing PDF page text', - product: 'pdfjs.document.pages', - type: 'performance', - data: { - file: this.props.file, - documentId: this.props.documentId, - }, - }; - - const pageAndTextFeatureToggle = this.props.featureToggles.metricsPdfStorePages; - const document = this.props.pdfDocument; - const pageIndex = pageNumberOfPageIndex(this.props.pageIndex); - const pageResult = recordAsyncMetrics(document.getPage(pageIndex), pageMetricData, pageAndTextFeatureToggle); - - pageResult.then((page) => { - this.page = page; - - const readerRenderText = { - uuid: uuidv4(), - message: 'Searching within Reader document text', - type: 'performance', - product: 'reader', - data: { - documentId: this.props.documentId, - documentType: this.props.documentType, - file: this.props.file - }, - }; - - const textResult = recordAsyncMetrics(this.getText(page), textMetricData, pageAndTextFeatureToggle); - - textResult.then((text) => { - recordMetrics(this.drawText(page, text), readerRenderText, - this.props.featureToggles.metricsReaderRenderText); - }); + this.getText(page).then((text) => { + this.drawText(page, text); + }); - this.drawPage(page).then(() => { - collectHistogram({ - group: 'front_end', - name: 'pdf_page_render_time_in_ms', - value: this.measureTimeStartMs ? performance.now() - this.measureTimeStartMs : 0, - appName: 'Reader', - attrs: { - documentId: this.props.documentId, - overscan: this.props.windowingOverscan, - documentType: this.props.documentType, - pageCount: this.props.pdfDocument.numPages - } + this.drawPage(page).then(() => { + collectHistogram({ + group: 'front_end', + name: 'pdf_page_render_time_in_ms', + value: this.measureTimeStartMs ? performance.now() - this.measureTimeStartMs : 0, + appName: 'Reader', + attrs: { + overscan: this.props.windowingOverscan, + documentType: this.props.documentType, + pageCount: this.props.pdfDocument.pdfInfo?.numPages + } + }); }); + }). + catch((error) => { + console.error(`${uuid.v4()} : setUpPage ${this.props.file} : ${error}`); }); - }).catch((error) => { - const id = uuid.v4(); - const data = { - documentId: this.props.documentId, - documentType: this.props.documentType, - file: this.props.file - }; - const message = `${id} : setUpPage ${this.props.file} : ${error}`; - - console.error(message); - storeMetrics( - id, - data, - { message, - type: 'error', - product: 'browser', - } - ); - }); } }; @@ -415,8 +358,7 @@ PdfPage.propTypes = { searchText: PropTypes.string, setDocScrollPosition: PropTypes.func, setSearchIndexToHighlight: PropTypes.func, - windowingOverscan: PropTypes.string, - featureToggles: PropTypes.object + windowingOverscan: PropTypes.string }; const mapDispatchToProps = (dispatch) => ({ diff --git a/client/app/reader/PdfUI.jsx b/client/app/reader/PdfUI.jsx index 3b4c28e932c..dafeb71ba0b 100644 --- a/client/app/reader/PdfUI.jsx +++ b/client/app/reader/PdfUI.jsx @@ -317,7 +317,7 @@ export class PdfUI extends React.Component {
- + + failStatusMessageChildren={failStatusMessageChildren}> {this.props.children} ; @@ -67,8 +66,7 @@ ReaderLoadingScreen.propTypes = { onReceiveAnnotations: PropTypes.func, onReceiveDocs: PropTypes.func, onReceiveManifests: PropTypes.func, - vacolsId: PropTypes.string, - featureToggles: PropTypes.object + vacolsId: PropTypes.string }; const mapStateToProps = (state) => ({ diff --git a/client/app/util/ApiUtil.js b/client/app/util/ApiUtil.js index cd36638d572..a1274bc2d4c 100644 --- a/client/app/util/ApiUtil.js +++ b/client/app/util/ApiUtil.js @@ -2,10 +2,8 @@ import request from 'superagent'; import nocache from 'superagent-no-cache'; import ReactOnRails from 'react-on-rails'; import StringUtil from './StringUtil'; -import uuid from 'uuid'; import _ from 'lodash'; import { timeFunctionPromise } from '../util/PerfDebug'; -import moment from 'moment'; export const STANDARD_API_TIMEOUT_MILLISECONDS = 60 * 1000; export const RESPONSE_COMPLETE_LIMIT_MILLISECONDS = 5 * 60 * 1000; @@ -42,125 +40,23 @@ export const getHeadersObject = (options = {}) => { return headers; }; -export const postMetricLogs = (data) => { - return request. - post('/metrics/v2/logs'). - set(getHeadersObject()). - send(data). - use(nocache). - on('error', (err) => console.error(`Metric not recorded\nUUID: ${uuid.v4()}.\n: ${err}`)). - end(); -}; - -// eslint-disable-next-line no-unused-vars -const errorHandling = (url, error, method, options = {}) => { - const id = uuid.v4(); - const message = `UUID: ${id}.\nProblem with ${method} ${url}.\n${error}`; - - console.error(new Error(message)); - options.t1 = performance.now(); - options.end = moment().format(); - options.duration = options.t1 - options.t0; - - // Need to renable this check before going to master - if (options?.metricsLogRestError) { - const data = { - metric: { - uuid: id, - name: `caseflow.client.rest.${method.toLowerCase()}.error`, - message, - type: 'error', - product: 'caseflow', - metric_attributes: JSON.stringify({ - method, - url, - error - }), - sent_to: 'javascript_console', - start: options.start, - end: options.end, - duration: options.duration, - } - }; - - postMetricLogs(data); - } -}; - -const successHandling = (url, res, method, options = {}) => { - const id = uuid.v4(); - const message = `UUID: ${id}.\nSuccess with ${method} ${url}.\n${res.status}`; - - // Need to renable this check before going to master - options.t1 = performance.now(); - options.end = moment().format(); - options.duration = options.t1 - options.t0; - - if (options?.metricsLogRestSuccess) { - const data = { - metric: { - uuid: id, - name: `caseflow.client.rest.${method.toLowerCase()}.info`, - message, - type: 'info', - product: 'caseflow', - metric_attributes: JSON.stringify({ - method, - url - }), - sent_to: 'javascript_console', - sent_to_info: JSON.stringify({ - metric_group: 'Rest call', - metric_name: 'Javascript request', - metric_value: options.duration, - app_name: 'JS reader', - attrs: { - service: 'rest service', - endpoint: url, - uuid: id - } - }), - - start: options.start, - end: options.end, - duration: options.duration, - } - }; - - postMetricLogs(data); - } -}; - const httpMethods = { delete(url, options = {}) { - options.t0 = performance.now(); - options.start = moment().format(); - return request. delete(url). set(getHeadersObject(options.headers)). send(options.data). - use(nocache). - on('error', (err) => errorHandling(url, err, 'DELETE', options)). - then((res) => { - successHandling(url, res, 'DELETE', options); - - return res; - }); + use(nocache); }, get(url, options = {}) { const timeoutSettings = Object.assign({}, defaultTimeoutSettings, _.get(options, 'timeout', {})); - options.t0 = performance.now(); - options.start = moment().format(); - let promise = request. get(url). set(getHeadersObject(options.headers)). query(options.query). - timeout(timeoutSettings). - on('error', (err) => errorHandling(url, err, 'GET', options)); + timeout(timeoutSettings); if (options.responseType) { promise.responseType(options.responseType); @@ -171,72 +67,36 @@ const httpMethods = { } if (options.cache) { - return promise. - then((res) => { - successHandling(url, res, 'GET', options); - return res; - }); + return promise; } return promise. - use(nocache). - then((res) => { - successHandling(url, res, 'GET', options); - return res; - }); + use(nocache); }, patch(url, options = {}) { - options.t0 = performance.now(); - options.start = moment().format(); - return request. post(url). set(getHeadersObject({ 'X-HTTP-METHOD-OVERRIDE': 'patch' })). send(options.data). - use(nocache). - on('error', (err) => errorHandling(url, err, 'PATCH', options)). - then((res) => { - successHandling(url, res, 'PATCH', options); - - return res; - }); + use(nocache); }, post(url, options = {}) { - options.t0 = performance.now(); - options.start = moment().format(); - return request. post(url). set(getHeadersObject(options.headers)). send(options.data). - use(nocache). - on('error', (err) => errorHandling(url, err, 'POST', options)). - then((res) => { - successHandling(url, res, 'POST', options); - - return res; - }); + use(nocache); }, put(url, options = {}) { - options.t0 = performance.now(); - options.start = moment().format(); - return request. put(url). set(getHeadersObject(options.headers)). send(options.data). - use(nocache). - on('error', (err) => errorHandling(url, err, 'PUT', options)). - then((res) => { - successHandling(url, res, 'PUT', options); - - return res; - }); + use(nocache); } - }; // TODO(jd): Fill in other HTTP methods as needed diff --git a/client/app/util/Metrics.js b/client/app/util/Metrics.js index 77d365a3f82..029aeeaafb3 100644 --- a/client/app/util/Metrics.js +++ b/client/app/util/Metrics.js @@ -1,141 +1,6 @@ -import ApiUtil, { postMetricLogs } from './ApiUtil'; +import ApiUtil from './ApiUtil'; import _ from 'lodash'; import moment from 'moment'; -import uuid from 'uuid'; - -// ------------------------------------------------------------------------------------------ -// Metric Storage and recording -// ------------------------------------------------------------------------------------------ - -const metricMessage = (uniqueId, data, message) => message ? message : `${uniqueId}\n${data}`; - -/** - * If a uuid wasn't provided assume that metric also wasn't sent to javascript console - * and send with UUID to console - */ -const checkUuid = (uniqueId, data, message, type) => { - let id = uniqueId; - const isError = type === 'error'; - - if (!uniqueId) { - id = uuid.v4(); - if (isError) { - console.error(metricMessage(uniqueId, data, message)); - } else { - // eslint-disable-next-line no-console - console.log(metricMessage(uniqueId, data, message)); - } - } - - return id; -}; - -/** - * uniqueId should be V4 UUID - * If a uniqueId is not presented one will be generated for it - * - * Data is an object containing information that will be stored in metric_attributes - * - * If a message is not provided one will be created based on the data passed in - * - * Product is which area of Caseflow did the metric come from: queue, hearings, intake, vha, case_distribution, reader - * - */ -export const storeMetrics = (uniqueId, data, { message, type = 'log', product, start, end, duration }) => { - const metricType = ['log', 'error', 'performance'].includes(type) ? type : 'log'; - const productArea = product ? product : 'caseflow'; - - const postData = { - metric: { - uuid: uniqueId, - name: `caseflow.client.${productArea}.${metricType}`, - message: metricMessage(uniqueId, data, message), - type: metricType, - product: productArea, - metric_attributes: JSON.stringify(data), - sent_to: 'javascript_console', - start, - end, - duration - } - }; - - postMetricLogs(postData); -}; - -export const recordMetrics = (targetFunction, { uniqueId, data, message, type = 'log', product }, - saveMetrics = true) => { - - let id = checkUuid(uniqueId, data, message, type); - - const t0 = performance.now(); - const start = Date.now(); - const name = targetFunction?.name || message; - - // eslint-disable-next-line no-console - console.info(`STARTED: ${id} ${name}`); - const result = () => targetFunction(); - const t1 = performance.now(); - const end = Date.now(); - - const duration = t1 - t0; - - // eslint-disable-next-line no-console - console.info(`FINISHED: ${id} ${name} in ${duration} milliseconds`); - - if (saveMetrics) { - const metricData = { - ...data, - name - }; - - storeMetrics(uniqueId, metricData, { message, type, product, start, end, duration }); - } - - return result; -}; - -/** - * Hopefully this doesn't cause issues and preserves the async of the promise or async function - * - * Might need to split into async and promise versions if issues - */ -export const recordAsyncMetrics = async (promise, { uniqueId, data, message, type = 'log', product }, - saveMetrics = true) => { - - let id = checkUuid(uniqueId, data, message, type); - - const t0 = performance.now(); - const start = Date.now(); - const name = message || promise; - - // eslint-disable-next-line no-console - console.info(`STARTED: ${id} ${name}`); - const prom = () => promise; - const result = await prom(); - const t1 = performance.now(); - const end = Date.now(); - - const duration = t1 - t0; - - // eslint-disable-next-line no-console - console.info(`FINISHED: ${id} ${name} in ${duration} milliseconds`); - - if (saveMetrics) { - const metricData = { - ...data, - name - }; - - storeMetrics(uniqueId, metricData, { message, type, product, start, end, duration }); - } - - return result; -}; - -// ------------------------------------------------------------------------------------------ -// Histograms -// ------------------------------------------------------------------------------------------ const INTERVAL_TO_SEND_METRICS_MS = moment.duration(60, 'seconds'); @@ -165,23 +30,4 @@ export const collectHistogram = (data) => { initialize(); histograms.push(ApiUtil.convertToSnakeCase(data)); - - const id = uuid.v4(); - const metricsData = data; - const time = Date(Date.now()).toString(); - const readerData = { - message: `Render document content for "${ data.attrs.documentType }"`, - type: 'performance', - product: 'pdfjs.document.render', - start: time, - end: Date(Date.now()).toString(), - duration: data.value, - }; - - if (data.value > 0) { - storeMetrics(id, metricsData, readerData); - } else if (data.attrs.pageCount < 2) { - storeMetrics(id, metricsData, readerData); - } }; - diff --git a/client/test/app/util/ApiUtil.test.js b/client/test/app/util/ApiUtil.test.js index 78924a0beee..bad4a427729 100644 --- a/client/test/app/util/ApiUtil.test.js +++ b/client/test/app/util/ApiUtil.test.js @@ -14,9 +14,7 @@ jest.mock('superagent', () => ({ set: jest.fn().mockReturnThis(), accept: jest.fn().mockReturnThis(), timeout: jest.fn().mockReturnThis(), - use: jest.fn().mockReturnThis(), - on: jest.fn().mockReturnThis(), - then: jest.fn().mockReturnThis() + use: jest.fn().mockReturnThis() })); const defaultHeaders = { @@ -55,25 +53,6 @@ describe('ApiUtil', () => { expect(request.use).toHaveBeenCalledWith(nocache); expect(req).toMatchObject(request); }); - - test('calls success handling method when calls the api request', () => { - const successHandling = jest.fn(); - - const res = {}; - - // Setup the test - const options = { data: { sample: 'data' } }; - - // Run the test - const req = ApiUtil.patch('/foo', options); - - // Expectations - req.then(() => { - // Assert that successHandling method is called - expect(request.then).toHaveBeenCalled(res); - expect(successHandling).toHaveBeenCalled(); - }) - }); }); describe('.post', () => { @@ -92,25 +71,6 @@ describe('ApiUtil', () => { expect(req).toMatchObject(request); }); - test('calls success handling method when calls the api request', () => { - const successHandling = jest.fn(); - - const res = {}; - - // Setup the test - const options = { data: { sample: 'data' } }; - - // Run the test - const req = ApiUtil.post('/bar', options); - - // Expectations - req.then(() => { - // Assert that successHandling method is called - expect(request.then).toHaveBeenCalled(res); - expect(successHandling).toHaveBeenCalled(); - }) - }); - test('attaches custom headers when provided', () => { // Setup the test const options = { headers: { sample: 'header' } }; @@ -167,24 +127,5 @@ describe('ApiUtil', () => { expect(request.use).toHaveBeenCalledWith(nocache); expect(req).toMatchObject(request); }); - - test('calls success handling method when calls the api request', () => { - const successHandling = jest.fn(); - - const res = {}; - - // Setup the test - const options = { query: { bar: 'baz' } }; - - // Run the test - const req = ApiUtil.get('/foo', options); - - // Expectations - req.then(() => { - // Assert that successHandling method is called - expect(request.then).toHaveBeenCalled(res); - expect(successHandling).toHaveBeenCalled(); - }) - }); }); }); diff --git a/config/routes.rb b/config/routes.rb index b13b2cc3cda..81670f08808 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -89,13 +89,8 @@ namespace :v1 do resources :histogram, only: :create end - namespace :v2 do - resources :logs, only: :create - end - get 'dashboard' => 'dashboard#show' end - namespace :dispatch do get "/", to: redirect("/dispatch/establish-claim") get 'missing-decision', to: 'establish_claims#unprepared_tasks' diff --git a/db/migrate/20230523174750_create_metrics_table.rb b/db/migrate/20230523174750_create_metrics_table.rb deleted file mode 100644 index 10e8aeb0598..00000000000 --- a/db/migrate/20230523174750_create_metrics_table.rb +++ /dev/null @@ -1,29 +0,0 @@ -class CreateMetricsTable < ActiveRecord::Migration[5.2] - def change - create_table :metrics do |t| - t.uuid :uuid, default: -> { "uuid_generate_v4()" }, null: false, comment: "Unique ID for the metric, can be used to search within various systems for the logging" - t.references :user, null: false, foreign_key: true, comment: "The ID of the user who generated metric." - t.string :metric_name, null: false, comment: "Name of metric" - t.string :metric_class, null: false, comment: "Class of metric, use reflection to find value to populate this" - t.string :metric_group, null: false, default: "service", comment: "Metric group: service, etc" - t.string :metric_message, null: false, comment: "Message or log for metric" - t.string :metric_type, null: false, comment: "Type of metric: ERROR, LOG, PERFORMANCE, etc" - t.string :metric_product, null: false, comment: "Where in application: Queue, Hearings, Intake, VHA, etc" - t.string :app_name, null: false, comment: "Application name: caseflow or efolder" - t.json :metric_attributes, comment: "Store attributes relevant to the metric: OS, browser, etc" - t.json :additional_info, comment: "additional data to store for the metric" - t.string :sent_to, array: true, comment: "Which system metric was sent to: Datadog, Rails Console, Javascript Console, etc " - t.json :sent_to_info, comment: "Additional information for which system metric was sent to" - t.json :relevant_tables_info, comment: "Store information to tie metric to database table(s)" - t.timestamp :start, comment: "When metric recording started" - t.timestamp :end, comment: "When metric recording stopped" - t.float :duration, comment: "Time in milliseconds from start to end" - t.timestamps - end - - add_index :metrics, :metric_name - add_index :metrics, :metric_product - add_index :metrics, :app_name - add_index :metrics, :sent_to - end -end diff --git a/db/schema.rb b/db/schema.rb index 32ca77d0c23..71f378159e5 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1251,33 +1251,6 @@ t.index ["updated_at"], name: "index_messages_on_updated_at" end - create_table "metrics", force: :cascade do |t| - t.json "additional_info", comment: "additional data to store for the metric" - t.string "app_name", null: false, comment: "Application name: caseflow or efolder" - t.datetime "created_at", null: false - t.float "duration", comment: "Time in milliseconds from start to end" - t.datetime "end", comment: "When metric recording stopped" - t.json "metric_attributes", comment: "Store attributes relevant to the metric: OS, browser, etc" - t.string "metric_class", null: false, comment: "Class of metric, use reflection to find value to populate this" - t.string "metric_group", default: "service", null: false, comment: "Metric group: service, etc" - t.string "metric_message", null: false, comment: "Message or log for metric" - t.string "metric_name", null: false, comment: "Name of metric" - t.string "metric_product", null: false, comment: "Where in application: Queue, Hearings, Intake, VHA, etc" - t.string "metric_type", null: false, comment: "Type of metric: ERROR, LOG, PERFORMANCE, etc" - t.json "relevant_tables_info", comment: "Store information to tie metric to database table(s)" - t.string "sent_to", comment: "Which system metric was sent to: Datadog, Rails Console, Javascript Console, etc ", array: true - t.json "sent_to_info", comment: "Additional information for which system metric was sent to" - t.datetime "start", comment: "When metric recording started" - t.datetime "updated_at", null: false - t.bigint "user_id", null: false, comment: "The ID of the user who generated metric." - t.uuid "uuid", default: -> { "uuid_generate_v4()" }, null: false, comment: "Unique ID for the metric, can be used to search within various systems for the logging" - t.index ["app_name"], name: "index_metrics_on_app_name" - t.index ["metric_name"], name: "index_metrics_on_metric_name" - t.index ["metric_product"], name: "index_metrics_on_metric_product" - t.index ["sent_to"], name: "index_metrics_on_sent_to" - t.index ["user_id"], name: "index_metrics_on_user_id" - end - create_table "mpi_update_person_events", force: :cascade do |t| t.bigint "api_key_id", null: false, comment: "API Key used to initiate the event" t.datetime "completed_at", comment: "Timestamp of when update was completed, regardless of success or failure" @@ -2163,7 +2136,6 @@ add_foreign_key "membership_requests", "users", column: "decider_id" add_foreign_key "membership_requests", "users", column: "requestor_id" add_foreign_key "messages", "users" - add_foreign_key "metrics", "users" add_foreign_key "mpi_update_person_events", "api_keys" add_foreign_key "nod_date_updates", "appeals" add_foreign_key "nod_date_updates", "users" diff --git a/spec/controllers/metrics/v2/logs_controller_spec.rb b/spec/controllers/metrics/v2/logs_controller_spec.rb deleted file mode 100644 index 23a824d7a94..00000000000 --- a/spec/controllers/metrics/v2/logs_controller_spec.rb +++ /dev/null @@ -1,44 +0,0 @@ -# frozen_string_literal: true - -describe Metrics::V2::LogsController, type: :controller do - let(:current_user) { create(:user) } - let(:request_params) do - { - metric: { - uuid: SecureRandom.uuid, - method: "123456789", - name: 'log', - group: 'service', - message: 'This is a test', - type: 'performance', - product: 'reader', - } - } - end - - before do - @raven_called = false - end - before { User.authenticate!(user: current_user) } - - context "with good request" do - it "returns 200 for request params" do - post :create, params: request_params - expect(@raven_called).to eq(false) - expect(response.status).to eq(200) - end - end - - context "With error type record to sentry" do - it "Records to Sentry" do - capture_raven_log - request_params[:metric][:type] = 'error' - post :create, params: request_params - expect(@raven_called).to eq(true) - end - end - - def capture_raven_log - allow(Raven).to receive(:capture_exception) { @raven_called = true } - end -end diff --git a/spec/jobs/update_appellant_representation_job_spec.rb b/spec/jobs/update_appellant_representation_job_spec.rb index 5bfe84c9db4..107e2975451 100644 --- a/spec/jobs/update_appellant_representation_job_spec.rb +++ b/spec/jobs/update_appellant_representation_job_spec.rb @@ -43,7 +43,7 @@ ) expect(DataDogService).to receive(:emit_gauge).with( app_name: "queue_job", - attrs: { endpoint: "AppellantNotification.appeal_mapper", service: "queue_job", uuid: anything }, + attrs: { endpoint: "AppellantNotification.appeal_mapper", service: "queue_job" }, metric_group: "service", metric_name: "request_latency", metric_value: anything diff --git a/spec/models/metric_spec.rb b/spec/models/metric_spec.rb deleted file mode 100644 index e18bc1a076c..00000000000 --- a/spec/models/metric_spec.rb +++ /dev/null @@ -1,50 +0,0 @@ -# frozen_string_literal: true - -describe Metric do - let(:user) { create(:user) } - - before { User.authenticate!(user: user) } - - describe "create_metric" do - let!(:params) do - { - uuid: SecureRandom.uuid, - method: "123456789", - name: 'log', - group: 'service', - message: 'This is a test', - type: 'performance', - product: 'reader', - } - end - - it "creates a javascript metric for performance" do - metric = Metric.create_metric(self, params, user) - - expect(metric.valid?).to be true - expect(metric.metric_type).to eq(Metric::METRIC_TYPES[:performance]) - end - - it "creates a javascript metric for log" do - params[:type] = 'log' - metric = Metric.create_metric(self, params, user) - - expect(metric.valid?).to be true - expect(metric.metric_type).to eq(Metric::METRIC_TYPES[:log]) - end - - it "creates a javascript metric for error" do - params[:type] = 'error' - metric = Metric.create_metric(self, params, user) - - expect(metric.valid?).to be true - expect(metric.metric_type).to eq(Metric::METRIC_TYPES[:error]) - end - - it "creates a javascript metric with invalid sent_to" do - metric = Metric.create_metric(self, params.merge({sent_to: 'fake'}), user) - - expect(metric.valid?).to be false - end - end -end