-
Notifications
You must be signed in to change notification settings - Fork 47
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
10432: Performance Measurement - TO TEST #5254
Changes from all commits
d0ab8ac
dd5e41e
b6f37f2
c5eb1e3
07380f6
3a38e1f
a39dbbd
87eb967
380c5c5
eff97a4
82848dc
941dbf5
ddd365a
57c3356
c89d7fe
d7e4767
a3b4380
4866e20
3fddf93
e78f332
7da2c74
ead4cf1
6851bf3
6ffe153
fcbab17
58e4f2c
21fc761
ee3ceb1
2191761
ce38cfa
9fc4074
4be1711
6bf5405
bef8820
fd7109d
e1bca79
2acf15e
0aee681
b3c03e9
4438256
a464e1d
c8e07c0
b991050
9379100
6085387
51e7282
03c6104
5263328
53d6ff7
e65b8f1
5fbcc6b
64322d8
7db5777
9219991
add497f
fbbc610
6abdc8f
e99fb8a
c9ccb80
8025ed9
93331f5
12de0a6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
#!/bin/bash | ||
|
||
# creates the entry for minimum time for sequence performance logging in the dynamo deploy table | ||
|
||
# Usage | ||
# ENV=dev ./setup-sequence-performance-minimum-time.sh | ||
|
||
./check-env-variables.sh \ | ||
"ENV" \ | ||
"AWS_SECRET_ACCESS_KEY" \ | ||
"AWS_ACCESS_KEY_ID" | ||
|
||
ITEM=$(cat <<-END | ||
{ | ||
"pk": { | ||
"S": "sequence-performance-minimum-time" | ||
}, | ||
"sk":{ | ||
"S": "sequence-performance-minimum-time" | ||
}, | ||
"current": { | ||
"N": "5" | ||
} | ||
} | ||
END | ||
) | ||
|
||
aws dynamodb put-item \ | ||
--region us-east-1 \ | ||
--table-name "efcms-deploy-${ENV}" \ | ||
--item "${ITEM}" |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,6 +46,7 @@ IRS_CLIENT_ID=$(aws cognito-idp list-user-pool-clients \ | |
echo "DAWSON_ENV='${ENV}'" | ||
echo "DYNAMODB_TABLE_NAME='${SOURCE_TABLE}'" | ||
echo "ELASTICSEARCH_ENDPOINT='${ELASTICSEARCH_ENDPOINT}'" | ||
echo "ELASTICSEARCH_INFO_ENDPOINT='${ELASTICSEARCH_INFO_ENDPOINT}'" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nitpick, and probably not worth doing if it involves changing infrastructure, but I wonder if we should give this a clearer name? |
||
echo "EMAIL_CHANGE_VERIFICATION_TEMPLATE='email_change_verification_${ENV}'" | ||
echo "EMAIL_DOCUMENT_SERVED_TEMPLATE='document_served_${ENV}'" | ||
echo "EMAIL_SERVED_PETITION_TEMPLATE='petition_served_${ENV}'" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { post } from '@shared/proxies/requests'; | ||
|
||
export const logUserPerformanceDataInteractor = ( | ||
applicationContext, | ||
performanceData: { | ||
sequenceName: string; | ||
duration: number; | ||
actionPerformanceArray: { actionName: string; duration: number }[]; | ||
}, | ||
) => { | ||
return post({ | ||
applicationContext, | ||
body: { performanceData }, | ||
endpoint: '/log/performance-data', | ||
}); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -127,6 +127,7 @@ import { getUsersPendingEmailLambda } from './lambdas/users/getUsersPendingEmail | |
import { getWorkItemLambda } from './lambdas/workitems/getWorkItemLambda'; | ||
import { ipLimiter } from './middleware/ipLimiter'; | ||
import { lambdaWrapper } from './lambdaWrapper'; | ||
import { logUserPerformanceDataLambda } from '@web-api/lambdas/system/logUserPerformanceDataLambda'; | ||
import { logger } from './logger'; | ||
import { loginLambda } from '@web-api/lambdas/auth/loginLambda'; | ||
import { opinionAdvancedSearchLambda } from './lambdas/documents/opinionAdvancedSearchLambda'; | ||
|
@@ -1072,6 +1073,16 @@ app.delete( | |
app.put('/work-items', lambdaWrapper(assignWorkItemsLambda)); | ||
} | ||
|
||
/** | ||
* logging | ||
*/ | ||
{ | ||
app.post( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could this contribute to high server load if we end up logging a lot? |
||
'/log/performance-data', | ||
lambdaWrapper(logUserPerformanceDataLambda), | ||
); | ||
} | ||
|
||
/** | ||
* system | ||
*/ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import { ROLES } from '@shared/business/entities/EntityConstants'; | ||
import { UnknownAuthUser } from '@shared/business/entities/authUser/AuthUser'; | ||
import { applicationContext } from '@shared/business/test/createTestApplicationContext'; | ||
import { logUserPerformanceDataInteractor } from '@web-api/business/useCases/system/logUserPerformanceDataInteractor'; | ||
|
||
describe('logUserPerformanceDataInteractor', () => { | ||
const TEST_EMAIL = 'TEST_EMAIL@EXAMPLE.COM'; | ||
|
||
const PERFORMANCE_DATA: { | ||
actionPerformanceArray: { actionName: string; duration: number }[]; | ||
duration: number; | ||
email: string; | ||
sequenceName: string; | ||
} = { | ||
actionPerformanceArray: [ | ||
{ actionName: 'TEST_ACTION_NAME_1', duration: 25 }, | ||
{ actionName: 'TEST_ACTION_NAME_2', duration: 25 }, | ||
{ actionName: 'TEST_ACTION_NAME_3', duration: 25 }, | ||
{ actionName: 'TEST_ACTION_NAME_4', duration: 25 }, | ||
], | ||
duration: 100, | ||
email: TEST_EMAIL, | ||
sequenceName: 'TEST_SEQUENCE_NAME', | ||
}; | ||
|
||
const TEST_USER: UnknownAuthUser = { | ||
email: TEST_EMAIL, | ||
name: 'TEST_NAME', | ||
role: ROLES.docketClerk, | ||
userId: 'SOME_TEST_USER_ID', | ||
}; | ||
|
||
beforeEach(() => { | ||
applicationContext | ||
.getPersistenceGateway() | ||
.saveSystemPerformanceData.mockImplementation(() => {}); | ||
}); | ||
|
||
it('should not allow unauthorized call to log data', async () => { | ||
await expect( | ||
logUserPerformanceDataInteractor( | ||
applicationContext, | ||
PERFORMANCE_DATA, | ||
undefined, | ||
), | ||
).rejects.toThrow('Unauthorized to log performance data'); | ||
}); | ||
|
||
it('should call persistence method with correct data', async () => { | ||
await logUserPerformanceDataInteractor( | ||
applicationContext, | ||
PERFORMANCE_DATA, | ||
TEST_USER, | ||
); | ||
|
||
const saveSystemPerformanceDataCalls = | ||
applicationContext.getPersistenceGateway().saveSystemPerformanceData.mock | ||
.calls; | ||
|
||
expect(saveSystemPerformanceDataCalls.length).toEqual(1); | ||
expect(saveSystemPerformanceDataCalls[0][0].performanceData).toEqual( | ||
PERFORMANCE_DATA, | ||
); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { ServerApplicationContext } from '@web-api/applicationContext'; | ||
import { UnauthorizedError } from '@web-api/errors/errors'; | ||
import { | ||
UnknownAuthUser, | ||
isAuthUser, | ||
} from '@shared/business/entities/authUser/AuthUser'; | ||
|
||
export const logUserPerformanceDataInteractor = async ( | ||
applicationContext: ServerApplicationContext, | ||
performanceData: { | ||
sequenceName: string; | ||
duration: number; | ||
actionPerformanceArray: { actionName: string; duration: number }[]; | ||
}, | ||
authorizedUser: UnknownAuthUser, | ||
): Promise<void> => { | ||
if (!isAuthUser(authorizedUser)) { | ||
throw new UnauthorizedError('Unauthorized to log performance data'); | ||
} | ||
|
||
const { email } = authorizedUser; | ||
await applicationContext.getPersistenceGateway().saveSystemPerformanceData({ | ||
applicationContext, | ||
performanceData: { | ||
...performanceData, | ||
email, | ||
}, | ||
}); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { UnknownAuthUser } from '@shared/business/entities/authUser/AuthUser'; | ||
import { genericHandler } from '@web-api/genericHandler'; | ||
|
||
export const logUserPerformanceDataLambda = ( | ||
event, | ||
authorizedUser: UnknownAuthUser, | ||
) => | ||
genericHandler(event, async ({ applicationContext }) => { | ||
const { performanceData } = JSON.parse(event.body); | ||
|
||
return await applicationContext | ||
.getUseCases() | ||
.logUserPerformanceDataInteractor( | ||
applicationContext, | ||
performanceData, | ||
authorizedUser, | ||
); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { | ||
MetricDatum, | ||
PutMetricDataCommand, | ||
PutMetricDataCommandInput, | ||
StandardUnit, | ||
} from '@aws-sdk/client-cloudwatch'; | ||
import { ServerApplicationContext } from '@web-api/applicationContext'; | ||
|
||
export const saveSystemPerformanceData = async ({ | ||
applicationContext, | ||
performanceData, | ||
}: { | ||
applicationContext: ServerApplicationContext; | ||
performanceData: { | ||
sequenceName: string; | ||
duration: number; | ||
actionPerformanceArray: { actionName: string; duration: number }[]; | ||
email: string; | ||
}; | ||
}) => { | ||
const { stage } = applicationContext.getEnvironment(); | ||
|
||
const cloudwatchClient = applicationContext.getCloudWatchClient(); | ||
const metricData: MetricDatum[] = [ | ||
{ | ||
Dimensions: [ | ||
{ Name: 'SequenceName', Value: performanceData.sequenceName }, | ||
], | ||
MetricName: 'SequenceDuration', | ||
Unit: 'Seconds', | ||
Value: performanceData.duration, | ||
}, | ||
...performanceData.actionPerformanceArray.map(action => ({ | ||
Dimensions: [ | ||
{ Name: 'SequenceName', Value: performanceData.sequenceName }, | ||
{ Name: 'ActionName', Value: action.actionName }, | ||
], | ||
MetricName: 'ActionPerformance', | ||
Unit: 'Seconds' as StandardUnit, | ||
Value: action.duration, | ||
})), | ||
]; | ||
|
||
const params: PutMetricDataCommandInput = { | ||
MetricData: metricData, | ||
Namespace: `System-Performance-Log-${stage}`, | ||
}; | ||
|
||
const command = new PutMetricDataCommand(params); | ||
|
||
await cloudwatchClient.send(command); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the reload? (Just making sure I understand!)