Skip to content

Commit

Permalink
test fe alerts
Browse files Browse the repository at this point in the history
  • Loading branch information
codemonkey800 committed Sep 7, 2023
1 parent 4624252 commit 74e7abf
Show file tree
Hide file tree
Showing 25 changed files with 426 additions and 212 deletions.
72 changes: 72 additions & 0 deletions .happy/terraform/modules/cloudwatch-alarm/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,25 @@ resource aws_cloudwatch_log_metric_filter data_workflows_plugin_update_successfu
}
}

resource aws_cloudwatch_log_metric_filter frontend_error {
name = "${var.stack_name}-frontend-error"
log_group_name = var.frontend_log_group_name
pattern = "{ $.level = \"error\" }"
count = var.metrics_enabled ? 1 : 0

metric_transformation {
name = "${var.stack_name}-frontend-error"
namespace = local.metrics_namespace
value = "1"
unit = "Count"
}
}

locals {
backend_api_500_log_metric_name = var.metrics_enabled ? aws_cloudwatch_log_metric_filter.backend_api_500_log_metric[0].name : "backend_api_500_log_metric"
data_workflows_metrics_update_successful_name = var.metrics_enabled ? aws_cloudwatch_log_metric_filter.data_workflows_metrics_update_successful[0].name : "data_workflows_metrics_update_successful"
data_workflows_plugin_update_successful_name = var.metrics_enabled ? aws_cloudwatch_log_metric_filter.data_workflows_plugin_update_successful[0].name : "data_workflows_plugin_update_successful"
frontend_error_name = var.metrics_enabled ? aws_cloudwatch_log_metric_filter.frontend_error[0].name : "frontend_error"
}

module backend_api_500_alarm {
Expand Down Expand Up @@ -257,3 +272,60 @@ module plugin_lambda_errors_alarm {
}]
tags = var.tags
}

module frontend_uncaught_error_alarm {
source = "terraform-aws-modules/cloudwatch/aws//modules/metric-alarm"
version = "3.3.0"

create_metric_alarm = var.alarms_enabled
alarm_name = "${var.stack_name}-frontend-uncaught-error-alarm"
alarm_description = "Errors that are not caught by any error handling on the frontend"
alarm_actions = [local.alarm_sns_arn]
comparison_operator = "GreaterThanOrEqualToThreshold"
evaluation_periods = 1
threshold = 0
datapoints_to_alarm = 1
metric_query = [
{
id = "error_sum"
return_data = true
expression = "SUM(METRICS())"
label = "Total Error Count"
},

{
id = "frontend_uncaught_error"
metric = [{
namespace = "AWS/RUM"
metric_name = "JsErrorCount"
period = local.period
stat = "Sum"
unit = "Count"

# dimensions = {
# application_name = var.frontend_rum_app_name
# }
}]
}
]
tags = var.tags
}

module frontend_error_alarm {
source = "terraform-aws-modules/cloudwatch/aws//modules/metric-alarm"
version = "3.3.0"

alarm_actions = [local.alarm_sns_arn]
alarm_description = "Errors that happen on the frontend that are handled by some form of error handling"
alarm_name = "${var.stack_name}-frontend-error-alarm"
comparison_operator = "GreaterThanOrEqualToThreshold"
create_metric_alarm = var.alarms_enabled
datapoints_to_alarm = 1
evaluation_periods = 1
metric_name = local.frontend_error_name
namespace = local.metrics_namespace
period = local.period
statistic = "Sum"
tags = var.tags
threshold = 2
}
10 changes: 10 additions & 0 deletions .happy/terraform/modules/cloudwatch-alarm/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,13 @@ variable stack_name {
variable tags {
type = map(string)
}

variable frontend_log_group_name {
type = string
description = "Log group name for frontend"
}

variable frontend_rum_app_name {
type = string
description = "App name for frontend RUM monitor"
}
5 changes: 4 additions & 1 deletion .happy/terraform/modules/ecs-stack/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,8 @@ resource "aws_lambda_function_event_invoke_config" "async-config" {
}

locals {
monitoring_enabled = var.env == "prod" || var.env == "staging"
# TODO revert this after testing
monitoring_enabled = var.env == "prod" || var.env == "staging" || var.env == "dev"
}

module alarm_and_monitoring {
Expand All @@ -685,4 +686,6 @@ module alarm_and_monitoring {
data_workflows_lambda_log_group_name = module.data_workflows_lambda.cloudwatch_log_group_name
plugins_lambda_function_name = module.plugins_lambda.function_name
tags = var.tags
frontend_log_group_name = module.frontend_service.cloudwatch_log_group_name
frontend_rum_app_name = local.cloudwatch_rum_config.app_name
}
4 changes: 4 additions & 0 deletions .happy/terraform/modules/service/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
output cloudwatch_log_group_name {
description = "The name of the Cloudwatch Log Group"
value = aws_cloudwatch_log_group.cloud_watch_logs_group.name
}
28 changes: 28 additions & 0 deletions frontend/src/components/HomePage/HomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,44 @@ import { Link } from '@/components/Link';
import { SearchBar } from '@/components/SearchBar';
import { SearchSection } from '@/components/SearchSection';
import { useOpenSearchPage } from '@/hooks/useOpenSearchPage';
import { Logger } from '@/utils';

import { FeaturedPlugins } from './FeaturedPlugins';
import { HomePageLayout } from './HomePageLayout';

const logger = new Logger('HomePage.tsx');

export function HomePage() {
const { t } = useTranslation(['homePage', 'common']);
const openSearchPage = useOpenSearchPage();

return (
<HomePageLayout>
<div className="flex items-center h-[80px] gap-3 justify-center">
<button
className="bg-hub-primary-200 p-2 rounded"
onClick={() => {
logger.error({
message: 'logging handled error',
error: 'some error happened',
});
}}
type="button"
>
throw handled error
</button>

<button
className="bg-hub-primary-200 p-2 rounded"
onClick={() => {
throw new Error('breh');
}}
type="button"
>
throw uncaught error
</button>
</div>

<SearchSection
title={t('homePage:discoverPlugins')}
subtitle={
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export type Styles = {
empty: string;
inline: string;
linkItem: string;
list: string;
Expand Down
17 changes: 15 additions & 2 deletions frontend/src/components/MetadataList/MetadataListMetadataItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import { useQuery } from 'react-query';
import { Link } from '@/components/Link';
import { MetadataKeys } from '@/context/plugin';
import { SUPPORTED_PYTHON_VERSIONS } from '@/store/search/filter.store';
import { PARAM_KEY_MAP, PARAM_VALUE_MAP } from '@/store/search/queryParameters';
import { SpdxLicenseResponse } from '@/store/search/types';
import { PARAM_KEY_MAP, PARAM_VALUE_MAP } from '@/store/search/utils';
import { PluginType, PluginWriterSaveLayer } from '@/types';
import { Logger } from '@/utils';
import { getErrorMessage } from '@/utils/error';
import { spdxLicenseDataAPI } from '@/utils/spdx';

import styles from './MetadataList.module.scss';
Expand Down Expand Up @@ -100,6 +102,8 @@ const METADATA_FILTER_LINKS = new Set<MetadataLinkKeys>([
'writerSaveLayers',
]);

const logger = new Logger('MetadataListMetadataItem.ts');

/**
* Component for rendering a metadata value.
*/
Expand All @@ -117,7 +121,16 @@ export function MetadataListMetadataItem({
const { data } = await spdxLicenseDataAPI.get<SpdxLicenseResponse>('');
return data.licenses;
},
{ enabled: metadataKey === 'license' },
{
enabled: metadataKey === 'license',
onError(err) {
logger.error({
message:
'Error fetching spdx license data for MetadataListMetadataItem',
error: getErrorMessage(err),
});
},
},
);

const isOsiApproved = useMemo(
Expand Down
7 changes: 6 additions & 1 deletion frontend/src/hooks/usePageTransitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useEffect, useRef } from 'react';
import { loadingStore } from '@/store/loading';
import { pageTransitionsStore } from '@/store/pageTransitions';
import { Logger } from '@/utils';
import { getErrorMessage } from '@/utils/error';

import { usePageUtils } from './usePageUtils';

Expand Down Expand Up @@ -62,7 +63,11 @@ export function usePageTransitions() {
}

const onError = (error: Error, url: string, event: RouteEvent) => {
logger.error('Error loading route:', error);
logger.error({
message: 'Error loading route:',
error: getErrorMessage(error),
});

onFinishLoading(url, event);
};

Expand Down
6 changes: 5 additions & 1 deletion frontend/src/hooks/usePlausible.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,11 @@ export function usePlausible() {
event: E,
...payload: Events[E][]
) {
logger.debug('Plausible event:', { event, payload });
logger.debug({
message: 'Plausible event',
event,
payload,
});

plausible(event, {
props: payload[0],
Expand Down
12 changes: 12 additions & 0 deletions frontend/src/hooks/usePluginMetrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ import { AxiosError } from 'axios';
import { useQuery, UseQueryOptions } from 'react-query';

import { PluginMetrics } from '@/types/metrics';
import { Logger } from '@/utils';
import { getErrorMessage } from '@/utils/error';
import { hubAPI } from '@/utils/HubAPIClient';

const logger = new Logger('usePluginMetrics');

export function usePluginMetrics(
plugin?: string,
options?: UseQueryOptions<PluginMetrics | undefined, AxiosError>,
Expand All @@ -15,6 +19,14 @@ export function usePluginMetrics(
() => (plugin ? hubAPI.getPluginMetrics(plugin) : undefined),
{
enabled,
onError(err) {
options?.onError?.(err);

logger.error({
message: 'Failed to fetch plugin metrics',
error: getErrorMessage(err),
});
},
...options,
},
);
Expand Down
18 changes: 9 additions & 9 deletions frontend/src/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import axios from 'axios';
import Head from 'next/head';
import { useTranslation } from 'next-i18next';
import { ReactNode } from 'react';
import { z } from 'zod';

import { ErrorMessage } from '@/components/ErrorMessage';
import { HomePage, HomePageProvider } from '@/components/HomePage';
import { PluginSectionsResponse, PluginSectionType } from '@/types';
import { Logger } from '@/utils';
import { getErrorMessage } from '@/utils/error';
import { hubAPI } from '@/utils/HubAPIClient';
import { getServerSidePropsHandler } from '@/utils/ssr';
import { getZodErrorMessage } from '@/utils/validate';

interface Props {
error?: string;
pluginSections?: PluginSectionsResponse;
}

const logger = new Logger('pages/index.ts');

export const getServerSideProps = getServerSidePropsHandler<Props>({
async getProps() {
const props: Props = {};
Expand All @@ -27,13 +28,12 @@ export const getServerSideProps = getServerSidePropsHandler<Props>({
PluginSectionType.recentlyUpdated,
]);
} catch (err) {
if (axios.isAxiosError(err)) {
props.error = err.message;
}
props.error = getErrorMessage(err);

if (err instanceof z.ZodError) {
props.error = getZodErrorMessage(err);
}
logger.error({
message: 'Failed to fetch plugin sections',
error: props.error,
});
}

return { props };
Expand Down
44 changes: 26 additions & 18 deletions frontend/src/pages/plugins/[name].tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { AxiosError } from 'axios';
import Head from 'next/head';
import { useTranslation } from 'next-i18next';
import { ParsedUrlQuery } from 'node:querystring';
import { z } from 'zod';

import { ErrorMessage } from '@/components/ErrorMessage';
import { PageMetadata } from '@/components/PageMetadata';
Expand All @@ -11,10 +9,10 @@ import { DEFAULT_REPO_DATA } from '@/constants/plugin';
import { useLoadingState } from '@/context/loading';
import { PluginStateProvider } from '@/context/plugin';
import { PluginData } from '@/types';
import { createUrl, fetchRepoData, FetchRepoDataResult } from '@/utils';
import { createUrl, fetchRepoData, FetchRepoDataResult, Logger } from '@/utils';
import { getErrorMessage } from '@/utils/error';
import { hubAPI } from '@/utils/HubAPIClient';
import { getServerSidePropsHandler } from '@/utils/ssr';
import { getZodErrorMessage } from '@/utils/validate';

/**
* Interface for parameters in URL.
Expand All @@ -30,9 +28,7 @@ interface BaseProps {

type Props = FetchRepoDataResult & BaseProps;

function isAxiosError(error: unknown): error is AxiosError {
return !!(error as AxiosError).isAxiosError;
}
const logger = new Logger('pages/plugins/[name].tsx');

export const getServerSideProps = getServerSidePropsHandler<Props, Params>({
/**
Expand All @@ -45,20 +41,32 @@ export const getServerSideProps = getServerSidePropsHandler<Props, Params>({
repo: DEFAULT_REPO_DATA,
};

try {
const data = await hubAPI.getPlugin(name);
props.plugin = data;
let codeRepo = '';

const result = await fetchRepoData(data.code_repository);
Object.assign(props, result);
try {
const plugin = await hubAPI.getPlugin(name);
codeRepo = plugin.code_repository;
props.plugin = plugin;
} catch (err) {
if (isAxiosError(err) || err instanceof Error) {
props.error = err.message;
}
props.error = getErrorMessage(err);
logger.error({
message: 'Failed to fetch plugin data',
plugin: name,
error: props.error,
});

return { props };
}

if (err instanceof z.ZodError) {
props.error = getZodErrorMessage(err);
}
const repoData = await fetchRepoData(codeRepo);
Object.assign(repoData, await fetchRepoData(codeRepo));

if (props.repoFetchError) {
logger.error({
message: 'Failed to fetch repo data',
plugin: name,
error: props.error,
});
}

return { props };
Expand Down
Loading

0 comments on commit 74e7abf

Please sign in to comment.