-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/main' into dependabot/npm_and_ya…
…rn/react-scripts-5.0.0
- Loading branch information
Showing
19 changed files
with
487 additions
and
107 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# 016 - Use OTEL for monitoring via New Relic | ||
|
||
We need a way to gather performance data and monitor our application. We also would like to receive alerts for particular error conditions so that we can investigate errors before they are reported by users. This means we need to choose a monitoring and observability library and backend to collect this data. | ||
|
||
## Considered Options | ||
|
||
### Open Telemetry | ||
|
||
Open Telemetry (OTEL) is an open source standard for application instrumentation. It consists of APIs, SDKs and tools for developers to instrument code in a standardized way. The protocol itself “describes the encoding, transport, and delivery mechanism of telemetry data between telemetry sources, intermediate nodes such as collectors and telemetry backends.” | ||
|
||
OTEL in a basic deployment consists of language libraries to instrument your code, an OTEL Collector which can receive the instrumented code, and an OTEL Exporter which sends the data to a configured backend. There are various open source backends (Jaeger, Zipkin) and many established monitoring services now support injesting OTEL metrics (New Relic, Honeycomb). | ||
|
||
### New Relic APM | ||
|
||
New Relic APM is an application performance monitoring SaaS platform. It consists of language libraries that auto instrument your code and display application performance metrics. The user typically does not write instrumentation on their own and instead relies on the auto-instrumentation. | ||
|
||
### Honeycomb | ||
|
||
Honeycomb is a datastore and query engine for observability data. It relies on OTEL libraries to do the instrumenting of your code and provides a datastore and query engine to explore the exported data. | ||
|
||
## Chosen Decision: Use OTEL with New Relic as the backend datastore. | ||
|
||
This decision really came down to the fact that CMS has a contract with New Relic and it is available to our team without needing to do any license aquisition. Since New Relic supports OTEL, we've decided to use OTEL instrumentation over New Relic's APM as we're seeing more of the monitoring and observability world embrace OTEL. This will allow us to choose a different backend in the future if we for any reason need to move providers. Choosing OTEL also pushes us to be more explicit about parts of the application we'd like to monitor, rather than being limited to only what auto instrumentation gives us from a product like NR APM. | ||
|
||
By combining OTEL with New Relic we also can use other New Relic features, like AWS infrastructure monitoring, uptime ping metrics, etc. | ||
|
||
### Pros/Cons | ||
|
||
#### OTEL | ||
|
||
- `+` Open Source solution that many monitoring vendors are standardizing on. | ||
- `+` Allows for both auto instrumentation and custom instrumentation. | ||
- `+` AWS provides a lambda layer that is easy to setup and get OTEL stats collected and exported. | ||
- `+` OSS backends like Jaeger allow us to run traces in local dev environments. | ||
- `-` High learning curve for our team to begin using. | ||
- `-` Not all parts of the OTEL standards are stable, particularly in metrics and logs. | ||
|
||
#### New Relic APM | ||
|
||
- `+` Easy to install and configure. Not much of a learning curve to get started. | ||
- `+` CMS already gives teams access to it. | ||
- `-` If we write custom traces for NR APM then that code only works for NR backend. | ||
|
||
#### Honeycomb | ||
|
||
- `+` Powerful query interface. | ||
- `+` Supports OTEL. | ||
- `-` CMS does not have a contract and we'd have to aquire a license on our own. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
27 changes: 27 additions & 0 deletions
27
services/app-web/src/components/ChangeHistory/ChangeHistory.module.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
@import '../../styles/uswdsImports.scss'; | ||
@import '../../styles/custom.scss'; | ||
|
||
.summarySection { | ||
background: $cms-color-white; | ||
line-height: units(3); | ||
@include u-radius('md'); | ||
|
||
h2 { | ||
margin: 0; | ||
@include u-text('normal'); | ||
} | ||
&:first-of-type { | ||
h2 { | ||
@include u-text('bold'); | ||
font-size: size('body', 'lg'); | ||
} | ||
} | ||
} | ||
|
||
.tag { | ||
font-weight: bold; | ||
} | ||
|
||
.accordionRows { | ||
font-size: 40px; | ||
} |
58 changes: 58 additions & 0 deletions
58
services/app-web/src/components/ChangeHistory/ChangeHistory.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { ChangeHistory } from './ChangeHistory' | ||
import { Submission2 } from '../../gen/gqlClient' | ||
|
||
export default { | ||
title: 'Components/ChangeHistory', | ||
component: ChangeHistory, | ||
} | ||
|
||
const submissionData: Submission2 = { | ||
id: '440d6a53-bb0a-49ae-9a9c-da7c5352789f', | ||
stateCode: 'MN', | ||
status: 'RESUBMITTED', | ||
intiallySubmittedAt: '2022-03-23', | ||
revisions: [ | ||
{ | ||
revision: { | ||
id: '26596de8-852d-4e42-bb0a-c9c9bf78c3de', | ||
unlockInfo: { | ||
updatedAt: '2022-03-24T01:18:44.663Z', | ||
updatedBy: 'zuko@example.com', | ||
updatedReason: 'testing stuff', | ||
__typename: 'UpdateInformation', | ||
}, | ||
submitInfo: { | ||
updatedAt: '2022-03-24T01:19:46.154Z', | ||
updatedBy: 'aang@example.com', | ||
updatedReason: 'Placeholder resubmission reason', | ||
__typename: 'UpdateInformation', | ||
}, | ||
createdAt: '2022-03-24T01:18:44.665Z', | ||
submissionData: 'alkdfjlasdjf', | ||
__typename: 'Revision', | ||
}, | ||
__typename: 'RevisionEdge', | ||
}, | ||
{ | ||
revision: { | ||
id: 'e048cdcf-5b19-4acb-8ead-d7dc2fd6cd30', | ||
unlockInfo: null, | ||
submitInfo: { | ||
updatedAt: '2022-03-23T02:08:52.259Z', | ||
updatedBy: 'aang@example.com', | ||
updatedReason: 'Initial submission', | ||
__typename: 'UpdateInformation', | ||
}, | ||
createdAt: '2022-03-23T02:08:14.241Z', | ||
submissionData: 'weoirna;dfkl', | ||
__typename: 'Revision', | ||
}, | ||
__typename: 'RevisionEdge', | ||
}, | ||
], | ||
__typename: 'Submission2', | ||
} | ||
|
||
export const DemoListUploadSuccess = (): React.ReactElement => { | ||
return <ChangeHistory submission={submissionData} /> | ||
} |
111 changes: 111 additions & 0 deletions
111
services/app-web/src/components/ChangeHistory/ChangeHistory.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import { render, screen } from '@testing-library/react' | ||
import userEvent from '@testing-library/user-event' | ||
import { ChangeHistory } from './ChangeHistory' | ||
import { Submission2 } from '../../gen/gqlClient' | ||
|
||
const submissionData: Submission2 = { | ||
id: '440d6a53-bb0a-49ae-9a9c-da7c5352789f', | ||
stateCode: 'MN', | ||
status: 'RESUBMITTED', | ||
intiallySubmittedAt: '2022-03-23', | ||
revisions: [ | ||
{ | ||
revision: { | ||
id: '26596de8-852d-4e42-bb0a-c9c9bf78c3de', | ||
unlockInfo: { | ||
updatedAt: '2022-03-24T01:18:44.663Z', | ||
updatedBy: 'zuko@example.com', | ||
updatedReason: 'testing stuff', | ||
__typename: 'UpdateInformation', | ||
}, | ||
submitInfo: { | ||
updatedAt: '2022-03-24T01:19:46.154Z', | ||
updatedBy: 'aang@example.com', | ||
updatedReason: 'Placeholder resubmission reason', | ||
__typename: 'UpdateInformation', | ||
}, | ||
createdAt: '2022-03-24T01:18:44.665Z', | ||
submissionData: 'qpoiuenad', | ||
__typename: 'Revision', | ||
}, | ||
__typename: 'RevisionEdge', | ||
}, | ||
{ | ||
revision: { | ||
id: 'e048cdcf-5b19-4acb-8ead-d7dc2fd6cd30', | ||
unlockInfo: null, | ||
submitInfo: { | ||
updatedAt: '2022-03-23T02:08:52.259Z', | ||
updatedBy: 'aang@example.com', | ||
updatedReason: 'Initial submission', | ||
__typename: 'UpdateInformation', | ||
}, | ||
createdAt: '2022-03-23T02:08:14.241Z', | ||
submissionData: 'nmzxcv;lasf', | ||
__typename: 'Revision', | ||
}, | ||
__typename: 'RevisionEdge', | ||
}, | ||
], | ||
__typename: 'Submission2', | ||
} | ||
|
||
describe('Change History', () => { | ||
it('renders without errors', () => { | ||
render(<ChangeHistory submission={submissionData} />) | ||
expect(screen.getByText('Change history')).toBeInTheDocument() | ||
}) | ||
|
||
it('includes an accordion list of changes', () => { | ||
render(<ChangeHistory submission={submissionData} />) | ||
expect(screen.getByTestId('accordion')).toBeInTheDocument() | ||
}) | ||
|
||
it('has expected text in the accordion title', () => { | ||
render(<ChangeHistory submission={submissionData} />) | ||
expect( | ||
screen.getByRole('button', { | ||
name: '03/23/22 9:19pm ET - Submission', | ||
}) | ||
).toBeInTheDocument() | ||
}) | ||
|
||
it('has expected text in the accordion content', () => { | ||
render(<ChangeHistory submission={submissionData} />) | ||
expect( | ||
screen.getByText('Placeholder resubmission reason') | ||
).toBeInTheDocument() | ||
}) | ||
|
||
it('should expand and collapse the accordion on click', () => { | ||
render(<ChangeHistory submission={submissionData} />) | ||
expect( | ||
screen.getByText('Placeholder resubmission reason') | ||
).not.toBeVisible() | ||
const accordionRows = screen.getAllByRole('button') | ||
userEvent.click(accordionRows[0]) | ||
expect( | ||
screen.getByText('Placeholder resubmission reason') | ||
).toBeVisible() | ||
userEvent.click(accordionRows[0]) | ||
expect( | ||
screen.getByText('Placeholder resubmission reason') | ||
).not.toBeVisible() | ||
}) | ||
it('should list the submission events in reverse chronological order', () => { | ||
render(<ChangeHistory submission={submissionData} />) | ||
expect( | ||
screen.getByText('Placeholder resubmission reason') | ||
).not.toBeVisible() | ||
const accordionRows = screen.getAllByRole('button') | ||
expect(accordionRows[0]).toHaveTextContent( | ||
'03/23/22 9:19pm ET - Submission' | ||
) | ||
expect(accordionRows[1]).toHaveTextContent( | ||
'03/23/22 9:18pm ET - Unlock' | ||
) | ||
expect(accordionRows[2]).toHaveTextContent( | ||
'03/22/22 10:08pm ET - Submission' | ||
) | ||
}) | ||
}) |
Oops, something went wrong.