Skip to content
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

Update core usage stats collection #85706

Merged
merged 5 commits into from
Dec 14, 2020

Conversation

jportner
Copy link
Contributor

@jportner jportner commented Dec 11, 2020

Resolves #85621.

Testing

Log into Kibana, navigate to Stack Management -> Advanced Settings, scroll to the bottom, click on the cluster data link, and Ctrl+F for "apiCalls". This will show you the cluster usage data payload, specifically the fields that this PR adds/changes.

@jportner jportner added v8.0.0 release_note:skip Skip the PR/issue when compiling release notes v7.11.0 labels Dec 11, 2020
@jportner jportner force-pushed the issue-85621-saved-object-usage-data branch 2 times, most recently from b46f5e6 to 673536b Compare December 12, 2020 06:01
Added fields for namespace (default or custom).
First implementation made a best-effort attempt to determine
whether or not a request was "first-party" (from the Kibana client)
by checking "kbn-version", "origin", and "referer". If these three
headers are all present, we thought it was very likely that the
request was first-party. However, further testing after adding
usage stats collection for additional SO APIs determined this to be
inaccurate; some actual first-party requests do not include the
"origin" header. I am not sure exactly why this is the case, but I
have changed the check to use "user-agent" instead. This is another
indicator that a request likely did not come from a programmatic
consumer.
@jportner jportner force-pushed the issue-85621-saved-object-usage-data branch from 673536b to 4d9d7f8 Compare December 12, 2020 17:54
Copy link
Contributor Author

@jportner jportner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Author's notes for reviewers.

Comment on lines 176 to +182
'apiCalls.savedObjectsImport.total': { type: 'long' },
'apiCalls.savedObjectsImport.kibanaRequest.yes': { type: 'long' },
'apiCalls.savedObjectsImport.kibanaRequest.no': { type: 'long' },
'apiCalls.savedObjectsImport.namespace.default.total': { type: 'long' },
'apiCalls.savedObjectsImport.namespace.default.kibanaRequest.yes': { type: 'long' },
'apiCalls.savedObjectsImport.namespace.default.kibanaRequest.no': { type: 'long' },
'apiCalls.savedObjectsImport.namespace.custom.total': { type: 'long' },
'apiCalls.savedObjectsImport.namespace.custom.kibanaRequest.yes': { type: 'long' },
'apiCalls.savedObjectsImport.namespace.custom.kibanaRequest.no': { type: 'long' },
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For each existing SO API, I removed these two usage stats fields in favor of these 6 additional ones. This gives us the ability to tell how many consumers, first- or third-party, are using SO APIs in non-default spaces.

src/core/server/core_usage_data/core_usage_stats_client.ts Outdated Show resolved Hide resolved
version: 'WzgsMV0=',
version: resp.body.saved_objects[1].version,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some SO API integration tests already had a "relaxed" version check like I've changed this to.

The usage stats collection additions caused flaky behavior for those tests that have "strict" version checks (version could be slightly different depending upon whether the usage stats incrementCounter finished before the operation in question, I am guessing). At any rate it seemed prudent to change these integration test assertions so that slight version deviations don't cause flaky behavior.

@jportner jportner marked this pull request as ready for review December 12, 2020 20:16
@jportner jportner requested review from a team as code owners December 12, 2020 20:16
Copy link
Contributor

@pgayvallet pgayvallet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good. Just got a question regarding the schema / data format

src/core/server/core_usage_data/core_usage_stats_client.ts Outdated Show resolved Hide resolved
src/core/server/core_usage_data/core_usage_stats_client.ts Outdated Show resolved Hide resolved
Comment on lines +186 to +187
const pathToCheck = this.basePath.remove(requestBasePath); // remove the server basePath from the request basePath
const matchResult = pathToCheck.match(SPACE_CONTEXT_REGEX); // Look for `/s/space-url-context` in the base path
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙈 , but I don't see any other easy option if we need this to be in core...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😬

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't tested this (sorry...not at my laptop at the moment), but could we infer this by checking to see if the requestBasePath === this.basePath.serverBasePath? If they match, then we'd be in the default space. If the request has a modified base path, then we'd be in the non-default space. This wouldn't account for users who explicitly target the default space via /s/default, but I'd expect (with no evidence) that this is uncommon.

Feel free to ignore this, just pitching a potential alternative

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested it and it does seem to work. I'd be hesitant to use this without accounting for /s/default, though, and we have an explicit check for that it doesn't really simplify our code. At least with the current approach, it's the same in Core and the Spaces plugin, so if it ever needs to change for some reason, it'll be more evident that the same change needs to be made in both places.

I'll leave it as-is for now and if we decide to revisit in #85869 we can do so.

Comment on lines +46 to +49
export const BULK_CREATE_STATS_PREFIX = 'apiCalls.savedObjectsBulkCreate';
export const BULK_GET_STATS_PREFIX = 'apiCalls.savedObjectsBulkGet';
export const BULK_UPDATE_STATS_PREFIX = 'apiCalls.savedObjectsBulkUpdate';
export const CREATE_STATS_PREFIX = 'apiCalls.savedObjectsCreate';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: I think I'm starting to see a factorizable pattern here 😅

Comment on lines +30 to +36
// Saved Objects Client APIs
'apiCalls.savedObjectsBulkCreate.total'?: number;
'apiCalls.savedObjectsBulkCreate.namespace.default.total'?: number;
'apiCalls.savedObjectsBulkCreate.namespace.default.kibanaRequest.yes'?: number;
'apiCalls.savedObjectsBulkCreate.namespace.default.kibanaRequest.no'?: number;
'apiCalls.savedObjectsBulkCreate.namespace.custom.total'?: number;
'apiCalls.savedObjectsBulkCreate.namespace.custom.kibanaRequest.yes'?: number;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this reflects the ES schema? Don't we want nested properties instead of flattening everything?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes this reflects the schema. In the original PR I had nested properties, but I flattened the fields so we could use the incrementCounter API to increment the counter fields instead of get+update. At any rate, the fields are flattened inside of ES so it doesn't make a difference for how we'll consume the usage data 🙂

@kibanamachine
Copy link
Contributor

💚 Build Succeeded

Metrics [docs]

Distributable file count

id before after diff
default 47129 47889 +760

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

Copy link
Member

@legrego legrego left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, code review only. Let me know if you'd like me to manually test, and I can do so tomorrow

Comment on lines +186 to +187
const pathToCheck = this.basePath.remove(requestBasePath); // remove the server basePath from the request basePath
const matchResult = pathToCheck.match(SPACE_CONTEXT_REGEX); // Look for `/s/space-url-context` in the base path
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't tested this (sorry...not at my laptop at the moment), but could we infer this by checking to see if the requestBasePath === this.basePath.serverBasePath? If they match, then we'd be in the default space. If the request has a modified base path, then we'd be in the non-default space. This wouldn't account for users who explicitly target the default space via /s/default, but I'd expect (with no evidence) that this is uncommon.

Feel free to ignore this, just pitching a potential alternative

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backported release_note:skip Skip the PR/issue when compiling release notes v7.11.0 v8.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add telemetry data for all saved objects APIs
4 participants