-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
Metering connector actions request body bytes #186804
Metering connector actions request body bytes #186804
Conversation
0d8dd42
to
1981342
Compare
e898038
to
4d180d6
Compare
/ci |
Pinging @elastic/response-ops (Team:ResponseOps) |
zipPassCode, | ||
}: SentinelOneFetchAgentFilesParams) { | ||
const agent = await this.getAgents({ uuid: agentUUID }); | ||
public async fetchAgentFiles( |
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.
@ersin-erdal ,
I read the PR description and just want to make sure that the changes done to these public methods have no impact on consumers of the COnnector's sub-actions - correct? The second argument (ConnectorMetricsCollector
) is something that the Action task runner will take care of internally?
Also,
Is there a way you can trigger the Security Solution tests (unit) to run on PR? They only currently run if files from the Security Solution plugin are changed, thus they did not run on this one. If needed, you can make a change (a JS comment would do, I think) to one of our files - perhaps one these:
- https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/sentinelone/sentinel_one_actions_client.ts
- https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/crowdstrike/crowdstrike_actions_client.ts
That should trigger CI to run our full test suite.
cc/ @tomsonpl - just FYI
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.
Correct, I intentionally didn't touch any params of the connector types, just passed the ConnectorMetricsCollector
as a second param.
Connector types just passes it to the request function, so it can collect the metrics there.
Then the Actions plugin will save the data collected by it, in event log.
There shouldn't be any change or impact on the connectors, they should work as they were.
I will add a comment in Security Solution as you suggest. Thanks.
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.
I didn't have a chance to do a complete review, but looked at connector_metrics_collector.ts
to see how we were implementing the core logic. Basic idea is sound, but I think we need to re-arrange the logic and add a try/catch on the stringify ...
}; | ||
|
||
public addRequestBodyBytes(result?: AxiosError | AxiosResponse, body: string | object = '') { | ||
const sBody = typeof body === 'string' ? body : JSON.stringify(body); |
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.
I don't have a great feeling about depending on axios to send a string | object
. Or, I'm afarid of using JSON.stringify()
without a try/catch - it can throw :-). I'd be ok with using a ${body}
version of the content length in case of an error.
Since this could be expensive, I think we should move this AFTER the Content-Length
check, since that seems highly likely to be the common case. So just check if Content-Length is there and return that, otherwise do the other calculations (stringify, byteLength, etc).
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.
It's not axios returning string | object
, it's us passing the body
as a fallback here, and we always pass it either as string or object. And breaking JSON.stringify is really hard, it just stringify what ever you pass :)
But you are right putting it after Content-Length
check is better.
Moved it and wrapped with try-catch just in case.
@@ -345,6 +356,7 @@ describe('createActionEventLogRecordObject', () => { | |||
], | |||
action: { | |||
name: 'test name', | |||
type_id: '.slack', |
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.
this must have been the source of the question on snake- vs camel- case hahahaha
This type_id
seems out of place to me. Is this the way we do it with rule id's?
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.
No it was SO name :) Like, action
or alert
.
This is a field name, it is the same for the rule, just the field name there is rule_type_id
... but rule.rule_type_id looks
weird to me...
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.
LGTM, thx for the changes and explanations, sorry for the delay!
…9-meter-request-bytes
💚 Build Succeeded
Metrics [docs]Public APIs missing comments
Public APIs missing exports
History
To update your PR or re-run it, just comment with: cc @ersin-erdal |
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.
Defend Workflows code review 👍 and testes crowdstrike connector
manually.
Thanks!
💔 All backports failed
Manual backportTo create the backport manually run:
Questions ?Please refer to the Backport tool documentation |
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.
queryParams?: SentinelOneGetActivitiesParams, | ||
connectorUsageCollector?: ConnectorUsageCollector |
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.
queryParams?: SentinelOneGetActivitiesParams, | |
connectorUsageCollector?: ConnectorUsageCollector | |
queryParams: SentinelOneGetActivitiesParams | undefined, | |
connectorUsageCollector: ConnectorUsageCollector |
params: queryParams, | ||
responseSchema: SentinelOneGetActivitiesResponseSchema, | ||
}, | ||
connectorUsageCollector! |
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.
if you apply the above suggestion then:
connectorUsageCollector! | |
connectorUsageCollector |
Resolves: elastic/response-ops-team#209 This PR is a follow-on of #186804. Creates a new task that runs every 1 hour to push the total connector-request-body-bytes that have been saved in the event log to usage-api.
Resolves: elastic/response-ops-team#209 This PR is a follow-on of elastic#186804. Creates a new task that runs every 1 hour to push the total connector-request-body-bytes that have been saved in the event log to usage-api. (cherry picked from commit 216f899)
Resolves: elastic/response-ops-team#209 This PR is a follow-on of elastic#186804. Creates a new task that runs every 1 hour to push the total connector-request-body-bytes that have been saved in the event log to usage-api.
Towards: https://github.com/elastic/response-ops-team/issues/209
This PR collects body-bytes from the requests made by the connectors to the 3rd parties and saves them in the event-log.
There is a new metric collector:
ConnectorMetricsCollector
Action TaskRunner, creates a new instance of it on each action execution and passes it to the actionType.executor.
Then the actionType.executor passes it to the request function provided by the actions plugin.
Request function passes the response (or the error) from axios to
addRequestBodyBytes
method of theConnectorMetricsCollector
.Since axios always returns
request.headers['Content-Length']
either in success result or error, metric collector uses its value to get the request body bytes.In case there is no
Content-Length
header,addRequestBodyBytes
method fallbacks to the body object that we pass as the second param. So It calculates the body bytes by usingBuffer.byteLength(body, 'utf8');
, which is also used by axios to populaterequest.headers['Content-Length']
For the connectors or the subActions that we don't use the request function or axios:
addRequestBodyBytes method is called just before making the request only with the body param in order to force it to use the fallback.
Note: If there are more than one requests in an execution, the bytes are summed.
To verify:
Create a rule with a connector that you would like to test.
Let the rule run and check the event-log of your connector, request body bytes should be saved in:
kibana.action.execution.metrics.request_body_bytes
Alternatively:
You can create a connector and run it on its test tab.
You can use the below query to check the event-log: