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

[Synthetics] Add push monitor api #131270

Merged

Conversation

dominiqueclarke
Copy link
Contributor

@dominiqueclarke dominiqueclarke commented Apr 29, 2022

Summary

Creates a new route for syncing push monitors with Monitor Management

[PUT] /api/synthetics/service/project/monitors

This route will handle creating new push monitors, updating existing push monitors, and, when requested, deleting stale push monitors.

This PR does not handle UI changes necessary to support push monitors with the UI Monitor Management table, including disabling editing of project monitors. That will be handled in a follow up PR.

Testing

Adding new monitors

curl -u elastic:changeme -X PUT "http://localhost:5601/api/synthetics/service/project/monitors" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d'
{
    "project": "test-project",
    "keep_stale": false,
    "monitors": [{
      "throttling": {
        "download": 5,
        "upload": 3,
        "latency": 20
      },
      "schedule": 10,
      "locations": [
        "us-east4-a"
      ],
      "params": {},
      "playwrightOptions": {
        "headless": true,
        "chromiumSandbox": false
      },
      "name": "check if title is present",
      "id": "check-if-title-is-present",
      "tags": [],
      "content": "UEsDBBQACAAIAON5qVQAAAAAAAAAAAAAAAAfAAAAZXhhbXBsZXMvdG9kb3MvYmFzaWMuam91cm5leS50c22Q0WrDMAxF3/sVF7MHB0LMXlc6RvcN+wDPVWNviW0sdUsp/fe5SSiD7UFCWFfHujIGlpnkybwxFTZfoY/E3hsaLEtwhs9RPNWKDU12zAOxkXRIbN4tB9d9pFOJdO6EN2HMqQguWN9asFBuQVMmJ7jiWNII9fIXrbabdUYr58l9IhwhQQZCYORCTFFUC31Btj21NRc7Mq4Nds+4bDD/pNVgT9F52Jyr2Fa+g75LAPttg8yErk+S9ELpTmVotlVwnfNCuh2lepl3+JflUmSBJ3uggt1v9INW/lHNLKze9dJe1J3QJK8pSvWkm6aTtCet5puq+x63+AFQSwcIAPQ3VfcAAACcAQAAUEsBAi0DFAAIAAgA43mpVAD0N1X3AAAAnAEAAB8AAAAAAAAAAAAgAKSBAAAAAGV4YW1wbGVzL3RvZG9zL2Jhc2ljLmpvdXJuZXkudHNQSwUGAAAAAAEAAQBNAAAARAEAAAAA",
      "filter": {
        "match": "check if title is present"
      }
    }
    ]
}
'

Expected output

{"createdMonitors":["check-if-title-is-present"],"updatedMonitors":[],"staleMonitors":[],"deletedMonitors":[],"failedMonitors":[]}

Testing that monitors were created successfully

Run this command to get the monitor

curl -u elastic:changeme -X GET "http://localhost:5601/qvb/internal/uptime/service/monitors?query=synthetics-monitor.attributes.journey_id%3A+check%20if%20title%20is%20present+AND+synthetics-monitor.attributes.project_id%3A+test-project" -H 'kbn-xsrf: true'

Grab the monitor id from the id property, then run the following command

curl -u elastic:changeme -X GET "http://localhost:5601/qvb/internal/uptime/service/monitors/{THE_ID}" -H 'kbn-xsrf: true'

Expected output

{
    "id": "2c712d60-cff3-11ec-8400-ab0987cebfd2",
    "type": "synthetics-monitor",
    "namespaces": [
        "default"
    ],
    "updated_at": "2022-05-09T23:53:07.138Z",
    "version": "WzQwOTgsMV0=",
    "attributes": {
        "type": "browser",
        "enabled": true,
        "schedule": {
            "number": 10,
            "unit": "m"
        },
        "service.name": "",
        "tags": [],
        "timeout": "16",
        "name": "check if title is present",
        "locations": [],
        "namespace": "default",
        "journey_id": "check-if-title-is-present",
        "project_id": "test-project",
        "playwright_options": "{\"headless\":true,\"chromiumSandbox\":false}",
        "is_push_monitor": true,
        "__ui": {
            "script_source": {
                "is_generated_script": false,
                "file_name": ""
            },
            "is_zip_url_tls_enabled": false
        },
        "params": "",
        "source.inline.script": "",
        "source.push.content": "UEsDBBQACAAIAON5qVQAAAAAAAAAAAAAAAAfAAAAZXhhbXBsZXMvdG9kb3MvYmFzaWMuam91cm5leS50c22Q0WrDMAxF3/sVF7MHB0LMXlc6RvcN+wDPVWNviW0sdUsp/fe5SSiD7UFCWFfHujIGlpnkybwxFTZfoY/E3hsaLEtwhs9RPNWKDU12zAOxkXRIbN4tB9d9pFOJdO6EN2HMqQguWN9asFBuQVMmJ7jiWNII9fIXrbabdUYr58l9IhwhQQZCYORCTFFUC31Btj21NRc7Mq4Nds+4bDD/pNVgT9F52Jyr2Fa+g75LAPttg8yErk+S9ELpTmVotlVwnfNCuh2lepl3+JflUmSBJ3uggt1v9INW/lHNLKze9dJe1J3QJK8pSvWkm6aTtCet5puq+x63+AFQSwcIAPQ3VfcAAACcAQAAUEsBAi0DFAAIAAgA43mpVAD0N1X3AAAAnAEAAB8AAAAAAAAAAAAgAKSBAAAAAGV4YW1wbGVzL3RvZG9zL2Jhc2ljLmpvdXJuZXkudHNQSwUGAAAAAAEAAQBNAAAARAEAAAAA",
        "source.zip_url.url": "",
        "source.zip_url.username": "",
        "source.zip_url.password": "",
        "source.zip_url.folder": "",
        "source.zip_url.proxy_url": "",
        "urls": "",
        "screenshots": "on",
        "synthetics_args": [],
        "filter_journeys.match": "check if title is present",
        "filter_journeys.tags": [],
        "ignore_https_errors": false,
        "throttling.is_enabled": true,
        "throttling.download_speed": "5",
        "throttling.upload_speed": "3",
        "throttling.latency": "20",
        "throttling.config": "5d/3u/20l",
        "ssl.certificate_authorities": "",
        "ssl.certificate": "",
        "ssl.key": "",
        "ssl.key_passphrase": "",
        "ssl.verification_mode": "full",
        "ssl.supported_protocols": [
            "TLSv1.1",
            "TLSv1.2",
            "TLSv1.3"
        ],
        "revision": 1
    },
    "references": [],
    "coreMigrationVersion": "8.3.0",
    "_inspect": []
}

Updating monitors

Run this command twice

curl -u elastic:changeme -X PUT "http://localhost:5601/api/synthetics/service/push/monitors" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d'
{
    "project": "test-project",
    "keep_stale": true,
    "monitors": [{
        "content": "test-content",
        "id": "test-id-1",
        "name": "test-name-1",
        "locations": ["US Central"],
        "schedule": "3m",
        "throttling": {
            "download": 20,
            "upload": 10,
            "latency": 20
        }
    },
    {
        "content": "test-content",
        "id": "test-id-2",
        "name": "test-name-2",
        "locations": ["US Central"],
        "schedule": "5m",
        "throttling": {
            "download": 10,
            "upload": 5,
            "latency": 20
        }
    }]
}
'

Expected output 1

{"createdMonitors":["test-id-1","test-id-2"],"updatedMonitors":[],"staleMonitors":[],"deletedMonitors":[],"failedMonitors":[]}

Expected output 2

{"createdMonitors":[],"updatedMonitors":["test-id-1","test-id-2"],"staleMonitors":[],"deletedMonitors":[],"failedMonitors":[]}

Testing reporting of stale monitors

Run this command which changes the id of one of the monitors

curl -u elastic:changeme -X PUT "http://localhost:5601/api/synthetics/service/push/monitors" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d'
{
    "project": "test-project",
    "keep_stale": true,
    "monitors": [{
        "content": "test-content",
        "id": "test-id-1",
        "name": "test-name-1",
        "locations": ["US Central"],
        "schedule": "5m",
        "throttling": {
            "download": 20,
            "upload": 10,
            "latency": 20
        }
    },
    {
        "content": "test-content",
        "id": "test-id-3",
        "name": "test-name-2",
        "locations": ["US Central"],
        "schedule": "5m",
        "throttling": {
            "download": 10,
            "upload": 5,
            "latency": 20
        }
    }]
}
'

Expected output

{"createdMonitors":["test-id-3"],"updatedMonitors":["test-id-1"],"staleMonitors":["test-id-2"],"deletedMonitors":[],"failedMonitors":[]}

Testing monitor deletion

Run command with keep_stale: false

curl -u elastic:changeme -X PUT "http://localhost:5601/api/synthetics/service/push/monitors" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d'
{
    "project": "test-project",
    "keep_stale": false,
    "monitors": [{
        "content": "test-content",
        "id": "test-id-1",
        "name": "test-name-1",
        "locations": ["US Central"],
        "schedule": "5m",
        "throttling": {
            "download": 20,
            "upload": 10,
            "latency": 20
        }
    },
    {
        "content": "test-content",
        "id": "test-id-3",
        "name": "test-name-2",
        "locations": ["US Central"],
        "schedule": "5m",
        "throttling": {
            "download": 10,
            "upload": 5,
            "latency": 20
        }
    }]
}
'

Expected output

{"createdMonitors":[],"updatedMonitors":["test-id-1"],"staleMonitors":[],"deletedMonitors":["test-id-2"],"failedMonitors":[]}

Readonly flow

Project monitors should be read only. The enabled toggle should display in a disabled state with a short tooltip explanation.

Screen Shot 2022-05-22 at 10 30 14 PM

When clicking the edit button, it will take you to a readonly version of the browser monitor configuration page.
Screen Shot 2022-05-22 at 10 30 32 PM

Note: Script is not able to be visuaized at this time, as it is first zipped then base64 encoded. Furher refinement is needed for displaying the file structure within the synthetics app.

@dominiqueclarke dominiqueclarke force-pushed the feature/synthetics-push-monitors branch from 1f2be8b to dead4ff Compare April 29, 2022 19:51
@dominiqueclarke dominiqueclarke force-pushed the feature/synthetics-push-monitors branch from ac4bc07 to 9071b40 Compare May 2, 2022 16:33
@dominiqueclarke dominiqueclarke changed the title adjust monitor schema [Synthetics] Add push monitor api May 10, 2022
@dominiqueclarke dominiqueclarke force-pushed the feature/synthetics-push-monitors branch from a2e6516 to 5cf6ffc Compare May 24, 2022 03:20
@dominiqueclarke
Copy link
Contributor Author

@elasticmachine merge upstream

@lucasfcosta
Copy link
Contributor

lucasfcosta commented May 24, 2022

Hey Dominique, I've E2E tested this in the following way and have some input to provide.

How I tested this PR.

  1. Checkout the service branch and run make build.
    Make sure to set HEARTBEAT_VERSION to 8.3.0-a2430aec-SNAPSHOT when starting it so that you have the latest good HB version.
  2. Create a new project using npx @elastic/synthetics init my-proj.
    There's a bug here registered at this issue. But for now you can npm run build the synthetics package and node ./dist/cli.js init my-proj.
  3. Write a few monitors in the journeys folder and save them.
    import { journey, step, monitor } from '@elastic/synthetics';
    
    journey('access-bbc', ({ page }) => {
      monitor.use({
        schedule: 15,
        throttling: { download: 10, latency: 11, upload: 12 },
      });
    
      step('go to BBC', async () => {
        await page.goto('https://bbc.co.uk');
      });
    });
    
    journey('access-google', ({ page }) => {
      step('go to google', async () => {
        await page.goto('https://google.com');
      });
    });
  4. Make sure that you have the right manifest file in Kibana settings so that you can translate the US East location's ID to your own localhost.
    {
      "throttling": {
        "download": 20,
        "upload": 10
      },
      "locations": {
        "us-east4-a": {
          "url": "https://localhost:10001",
          "geo": {
            "name": "US East [GA]",
            "location": {"lat": 41.25, "lon": -95.86}
          },
          "status": "ga"
        },
        "Bin One": {
          "url": "http://localhost:8033",
          "geo": {
            "name": "BIN ONE",
            "location": {"lat": 41.25, "lon": -95.86}
          },
          "status": "experimental"
        },
        "Bin Two": {
          "url": "http://localhost:8034",
          "geo": {
            "name": "BIN TWO",
            "location": {"lat": 41.25, "lon": -95.86}
          },
          "status": "experimental"
        }
      }
    }
  5. Create a few request bins to ensure requests are only sent to the service, not to the bins.
    docker run -p 8033:80 -t mendhak/http-https-echo
    docker run -p 8034:80 -t mendhak/http-https-echo
    
  6. Serve your manifest, make sure Kibana settings point to it, and start Kibana:
    # You can serve the manifest with `npx http-server your_folder_with_manifest --port 8081`
    xpack.uptime.service.manifestUrl: http://localhost:8081/manifest.json
    
    # Disable this one
    # xpack.uptime.service.devUrl: https://localhost:10001
  7. Push your monitors!
    ➡️ Without setting locations you'll get requests on all of the manifest's location.
    synthetics push ./my-proj/journeys --auth elastic:changeme --url http://localhost:5602/vzh --project abc
    
  8. Now, try setting locations on your synthetics config file:
    import type { SyntheticsConfig } from '@elastic/synthetics';
    
    export default () => {
      const config: SyntheticsConfig = {
        playwrightOptions: {
          ignoreHTTPSErrors: true,
        },
        monitor: {
          locations: ['US East'],
        },
      };
      return config;
    };
  9. Pushing monitors again should only push monitors to US East (which points to localhost:10001 in your manifest) not to the request bins.
  10. You should also try setting locations straight on the monitors.
    import { journey, step, monitor } from '@elastic/synthetics';
    
    journey('visit-bbc', ({ page }) => {
      monitor.use({
        schedule: 15,
        throttling: { download: 10, latency: 11, upload: 12 },
        monitor: {
          locations: ['US East'],
        },
      });
    
      step('go to BBC', async () => {
        await page.goto('https://bbc.co.uk');
      });
    });
    
    journey('visit-google', ({ page }) => {
      monitor.use({
        schedule: 15,
        throttling: { download: 10, latency: 11, upload: 12 },
        monitor: {
          locations: ['US East'],
        },
      });
    
      step('go to google', async () => {
        await page.goto('https://google.com');
      });
    });
  11. After pushing monitors, go into Kibana and try to edit them. You should not be able to edit these monitors and fields should be disabled.
  12. You should also be getting results back from the pushed monitors.
    In my example BBC did timeout because I had an unstable connection, but it eventually passed.
    Screenshot 2022-05-24 at 14 38 12
  13. After seeing those I've also deleted one of the monitors and re-pushed them using the --delete flag to be sure only one monitor would remain.
    import { journey, step, monitor } from '@elastic/synthetics';
    
    journey('visit-bbc', ({ page }) => {
      monitor.use({
        schedule: 15,
        throttling: { download: 10, latency: 11, upload: 12 },
        monitor: {
          locations: ['US East'],
        },
      });
    
      step('go to BBC', async () => {
        await page.goto('https://bbc.co.uk');
      });
    });
    
    // Deleted the other monitor
    synthetics push ./my-proj/journeys --auth elastic:changeme --url http://localhost:5602/vzh --project abc --delete
    

Possible Gotchas

  • Ensure you're using a good build of HB. I'm currently testing on 8.3.0-a2430aec-SNAPSHOT.
  • If you're running ES locally, ensure the address for pods to index back results is the one which minikube resolves to the underlying host (most of the times it's the one below, but it also appears if you run make start, right at the end of its output)
    xpack.uptime.service.hosts: ["http://192.168.64.1:9200"]
    

Open Questions/Input

  • Shouldn't we allow editing a monitor's enabled/disabled status even when they're pushed through a project?
  • Although I can't edit any fields, some of them don't appear to be styled as "disabled" to me.
    Screenshot 2022-05-24 at 15 05 19

@dominiqueclarke dominiqueclarke force-pushed the feature/synthetics-push-monitors branch from 34ced55 to 143bb63 Compare May 24, 2022 15:25
@dominiqueclarke
Copy link
Contributor Author

@lucasfcosta We've discussed enabled/disabled offline.
For the disabled state UX, @hbharding 's guidance is to use the readOnly state of fields when available and disabled when not. Unfortunately, not all field inputs have a readOnly state, so we have to fall back to disabled

@shahzad31
Copy link
Contributor

Test it e2e and it's working now

Copy link
Contributor

@shahzad31 shahzad31 left a comment

Choose a reason for hiding this comment

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

LGTM !!

Working e2e

@kibana-ci
Copy link
Collaborator

💛 Build succeeded, but was flaky

Failed CI Steps

Test Failures

  • [job] [logs] FTR Configs #39 / Actions and Triggers app rules list should display total alerts by status and error banner only when exists alerts with status error
  • [job] [logs] FTR Configs #2 / rules security and spaces enabled: basic ruleRegistryAlertsSearchStrategy logs should return alerts from log rules

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
synthetics 808 810 +2

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
synthetics 821.9KB 829.2KB +7.3KB

History

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

@dominiqueclarke dominiqueclarke merged commit 16e12a2 into elastic:main May 24, 2022
@dominiqueclarke dominiqueclarke deleted the feature/synthetics-push-monitors branch May 24, 2022 19:18
@kibanamachine kibanamachine added the backport:skip This commit does not require backporting label May 24, 2022
@emilioalvap emilioalvap self-assigned this Jun 7, 2022
@emilioalvap
Copy link
Contributor

PostFF LGTM, tested following @lucasfcosta 's instructions.

@emilioalvap emilioalvap removed their assignment Jun 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:skip This commit does not require backporting enhancement New value added to drive a business result release_note:skip Skip the PR/issue when compiling release notes Team:Uptime - DEPRECATED Synthetics & RUM sub-team of Application Observability v8.3.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants