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

[Screenshot mode] Create plugin to provide "screenshot mode" awareness #99627

Merged
merged 23 commits into from
May 19, 2021

Conversation

jloleysens
Copy link
Contributor

@jloleysens jloleysens commented May 10, 2021

Summary

Fixes #99011

This contribution adds the new screenshot mode low-level plugin (a plugin that does not depend on other plugins) to Kibana.

The consumer plugins of this plugin should typically be fairly low-level plugins. This provides a way for resources (code, data, network requests) to not be loaded unnecessarily for an environment flagged as intended for screenshots (i.e., no user interaction). For example it does not make sense to report UI telemetry (client side) or API usage telemetry (server side).

Client-side

We expose a service that can be used by consumers to determine whether we are in screenshot mode. Screenshot mode should be detected pre-setup phase to expose this information before services or resources are started.

Server-side

We expose a flag request handler context object (RequestHandlerContext) to indicate that a request originated from a client that has optimised for taking screenshots.

To reviewers

  • (to all) Please see the example screenshot plugin for details on when/how the service can be consumed.
  • (to kibana ops) The current implementation uses require to a load a function from a file in the screenshot mode service that is passed into puppeteer, not sure whether this might have implications for any release builds? (see x-pack/plugins/reporting/server/browsers/chromium/driver/chromium_driver.ts)
  • (to security) will this usable for particular server-side use-cases?

Additional notes

The intended use case, per the README, is not to be used by higher-level plugins for determining when to render a reporting or print-friendly layout. The recommendation is to rather create a dedicated app route that loads only the UI and resources needed by the app.

Checklist

Delete any items that are not applicable to this PR.

@jloleysens jloleysens added v8.0.0 Team:AppServices release_note:skip Skip the PR/issue when compiling release notes v7.14.0 labels May 10, 2021
@jloleysens
Copy link
Contributor Author

@elasticmachine merge upstream

@jloleysens
Copy link
Contributor Author

@elasticmachine merge upstream

@jloleysens
Copy link
Contributor Author

@elasticmachine merge upstream

@jloleysens jloleysens marked this pull request as ready for review May 14, 2021 09:37
@jloleysens jloleysens requested review from a team as code owners May 14, 2021 09:37
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-app-services (Team:AppServices)

@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-reporting-services (Team:Reporting Services)

Added a server-side example for screenshot mode
Export the screenshot mode header in both public and server
Copy link
Member

@mistic mistic left a comment

Choose a reason for hiding this comment

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

Changes under operations team code owners LGTM

Copy link
Member

@tsullivan tsullivan left a comment

Choose a reason for hiding this comment

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

Just two minor comments for now

* Side Public License, v 1.
*/

export const KBN_SCREENSHOT_MODE_HEADER = 'x-kbn-screenshot-mode'.toLowerCase();
Copy link
Member

Choose a reason for hiding this comment

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

Looks like .toLowerCase() can be removed

* localStorage. The ability to set a value in localStorage enables more convenient development and testing
* in functionality that needs to detect screenshot mode.
*/
export const getScreenshotMode = (): unknown => {
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't this return a boolean?

@jloleysens
Copy link
Contributor Author

@elasticmachine merge upstream

@@ -0,0 +1,51 @@
/*
Copy link
Member

Choose a reason for hiding this comment

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

question: Just out of curiosity, I see this common file has a hard dependency on window, how does this code work on the server side?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's a good question, it doesn't 😅 . It is intended for use by reporting which injects this function into the "preload" phase of opening a page.

Happy to capture that in a comment or consider a different implementation. WDYT?

Copy link
Member

Choose a reason for hiding this comment

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

That makes sense, thanks! I think mentioning this in the comment would be beneficial, just in case someone like me stumbles upon this file in the future.

Copy link
Member

Choose a reason for hiding this comment

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

++ it took me a minute to understand it too - but it's pretty cool how it works


export class ScreenshotModePlugin implements Plugin<ScreenshotModePluginSetup> {
public setup(core: CoreSetup) {
core.http.registerRouteHandlerContext<ScreenshotModeRequestHandlerContext, 'screenshotMode'>(
Copy link
Member

Choose a reason for hiding this comment

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

issue: having isScreenshot in the request context is great, but unfortunately request context isn't available during authentication. Authentication is performed within auth handler that doesn't have access to the request context.

Maybe you can expose an additional method from the start or setup (or both) contract too, so that the code that doesn't have access to request context for one reason or another can use it instead (with a drawback of having dependency on screenshotMode plugin)?

public setup/start() {
  return {
    isScreenshot: (request: KibanaRequest) =>
      Object.keys(request.headers).some((header) => {
        return header.toLowerCase() === KBN_SCREENSHOT_MODE_HEADER;
      }),
  };
}

In the future, I believe the Kibana platform should be the one who determines in which mode Kibana is used. This way it can extend KibanaRequest with additional property or propagate this knowledge to plugins in any other way without introducing additional plugin dependencies. But it's too early to generalize, let's see if this solution is enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the input @azasypkin , that trade-off makes sense to me!

* references as possible to make it portable. For instance, running inside puppeteer.
*/
export const setScreenshotModeEnabled = () => {
Object.defineProperty(window, '__KBN_SCREENSHOT_MODE_ENABLED_KEY__', {
Copy link
Member

Choose a reason for hiding this comment

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

question: Btw, should we use constant here (and in setScreenshotModeDisabled)?

Suggested change
Object.defineProperty(window, '__KBN_SCREENSHOT_MODE_ENABLED_KEY__', {
Object.defineProperty(window, KBN_SCREENSHOT_MODE_ENABLED_KEY, {

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because this function is used in puppeteer it cannot have references to external variables that are not available from within the puppeteer environment where this code is run.

I'll add an inline comment to this effect.

Copy link
Member

@azasypkin azasypkin left a comment

Choose a reason for hiding this comment

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

The API exposed by the screenshotMode plugin LGTM, thanks!

@jloleysens
Copy link
Contributor Author

@elasticmachine merge upstream

@jloleysens
Copy link
Contributor Author

@elasticmachine merge upstream

@kibanamachine
Copy link
Contributor

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
screenshotMode - 8 +8

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
reporting 130 132 +2
screenshotMode - 9 +9
total +11

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
screenshotMode - 3.0KB +3.0KB
Unknown metric groups

API count

id before after diff
reporting 131 133 +2
screenshotMode - 13 +13
total +15

References to deprecated APIs

id before after diff
canvas 29 25 -4
crossClusterReplication 8 6 -2
fleet 22 20 -2
globalSearch 4 2 -2
indexManagement 12 7 -5
licensing 18 15 -3
maps 286 208 -78
ml 121 115 -6
monitoring 109 56 -53
stackAlerts 101 95 -6
total -161

History

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

@jloleysens jloleysens merged commit f97aad3 into elastic:master May 19, 2021
@jloleysens jloleysens deleted the screenshot-mode/create-plugin branch May 19, 2021 14:03
jloleysens added a commit to jloleysens/kibana that referenced this pull request May 19, 2021
elastic#99627)

* initial version of the screenshot mode service

* First iteration of client side of screenshot mode plugin

Also hooked it up to the chromium browser imitating the preload
functionality of electron to set up the environment before
code runs.

* First implementation of server-side logic for detecting
screenshot mode

* fix some type issues and do a small refactor

* fix size limits, docs and ts issues

* fixed types issues and made sure screenshot mode is correctly detected on the client

* Moved the screenshot mode header definition to common
Added a server-side example for screenshot mode
Export the screenshot mode header in both public and server

* move require() to screenshotMode plugin

* Update chromium_driver.ts

* cleaned up some comments, minor refactor in ReportingCore and
changed the screenshotmode detection function to check for a
specific value.

* fix export

* Expanded server-side screenshot mode contract with function that
checks a kibana request to determine whether we in screenshot
mode

* added comments to explain use of literal value rather than external reference

* updated comment

* update reporting example

Co-authored-by: Kibana Machine <[email protected]>
Co-authored-by: Timothy Sullivan <[email protected]>
Co-authored-by: Tim Sullivan <[email protected]>
# Conflicts:
#	x-pack/plugins/reporting/server/core.ts
#	x-pack/plugins/reporting/server/plugin.ts
Copy link
Member

@tsullivan tsullivan left a comment

Choose a reason for hiding this comment

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

LGTM!

jloleysens added a commit that referenced this pull request May 20, 2021
…areness (#99627) (#100331)

* [Screenshot mode] Create plugin to provide "screenshot mode" awareness (#99627)

* initial version of the screenshot mode service

* First iteration of client side of screenshot mode plugin

Also hooked it up to the chromium browser imitating the preload
functionality of electron to set up the environment before
code runs.

* First implementation of server-side logic for detecting
screenshot mode

* fix some type issues and do a small refactor

* fix size limits, docs and ts issues

* fixed types issues and made sure screenshot mode is correctly detected on the client

* Moved the screenshot mode header definition to common
Added a server-side example for screenshot mode
Export the screenshot mode header in both public and server

* move require() to screenshotMode plugin

* Update chromium_driver.ts

* cleaned up some comments, minor refactor in ReportingCore and
changed the screenshotmode detection function to check for a
specific value.

* fix export

* Expanded server-side screenshot mode contract with function that
checks a kibana request to determine whether we in screenshot
mode

* added comments to explain use of literal value rather than external reference

* updated comment

* update reporting example

Co-authored-by: Kibana Machine <[email protected]>
Co-authored-by: Timothy Sullivan <[email protected]>
Co-authored-by: Tim Sullivan <[email protected]>
# Conflicts:
#	x-pack/plugins/reporting/server/core.ts
#	x-pack/plugins/reporting/server/plugin.ts

* satisfy for tslint formatting

Co-authored-by: Kibana Machine <[email protected]>
yctercero pushed a commit to yctercero/kibana that referenced this pull request May 25, 2021
elastic#99627)

* initial version of the screenshot mode service

* First iteration of client side of screenshot mode plugin

Also hooked it up to the chromium browser imitating the preload
functionality of electron to set up the environment before
code runs.

* First implementation of server-side logic for detecting
screenshot mode

* fix some type issues and do a small refactor

* fix size limits, docs and ts issues

* fixed types issues and made sure screenshot mode is correctly detected on the client

* Moved the screenshot mode header definition to common
Added a server-side example for screenshot mode
Export the screenshot mode header in both public and server

* move require() to screenshotMode plugin

* Update chromium_driver.ts

* cleaned up some comments, minor refactor in ReportingCore and
changed the screenshotmode detection function to check for a
specific value.

* fix export

* Expanded server-side screenshot mode contract with function that
checks a kibana request to determine whether we in screenshot
mode

* added comments to explain use of literal value rather than external reference

* updated comment

* update reporting example

Co-authored-by: Kibana Machine <[email protected]>
Co-authored-by: Timothy Sullivan <[email protected]>
Co-authored-by: Tim Sullivan <[email protected]>
@sophiec20 sophiec20 added the (Deprecated) Feature:Reporting Use Reporting:Screenshot, Reporting:CSV, or Reporting:Framework instead label Aug 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
(Deprecated) Feature:Reporting Use Reporting:Screenshot, Reporting:CSV, or Reporting:Framework instead release_note:skip Skip the PR/issue when compiling release notes v7.14.0 v8.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Reporting/AppServices] Implement Screenshot Mode Service
8 participants