diff --git a/Dockerfile b/Dockerfile index 979a32881..a8518e833 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,6 +8,9 @@ FROM blazemeter/taurus ENV APT_INSTALL="apt-get -y install --no-install-recommends" +# Remove bintray manually until PR https://github.com/Blazemeter/taurus/pull/1484/files is promoted to prod +RUN sed -i '/dl.bintray.com/d' /etc/apt/sources.list + RUN apt-get -y update \ && $APT_INSTALL vim git openssh-server python3.8-dev python3-pip wget \ && update-alternatives --install /usr/bin/python python /usr/bin/python3.8 1 \ diff --git a/README.md b/README.md index 70f35eaaf..f5fe77c47 100644 --- a/README.md +++ b/README.md @@ -5,19 +5,22 @@ This repository contains Taurus scripts for performance testing of Atlassian Dat ## Supported versions * Supported Jira versions: - * Jira [Long Term Support release](https://confluence.atlassian.com/enterprise/atlassian-enterprise-releases-948227420.html): `8.13.4`, `8.5.12` + * Jira [Long Term Support release](https://confluence.atlassian.com/enterprise/atlassian-enterprise-releases-948227420.html): `8.13.7`, `8.5.15` * Supported Jira Service Management versions: - * Jira Service Management [Long Term Support release](https://confluence.atlassian.com/enterprise/atlassian-enterprise-releases-948227420.html): `4.13.4`, `4.5.12` + * Jira Service Management [Long Term Support release](https://confluence.atlassian.com/enterprise/atlassian-enterprise-releases-948227420.html): `4.13.7`, `4.5.15` * Supported Confluence versions: - * Confluence [Long Term Support release](https://confluence.atlassian.com/enterprise/atlassian-enterprise-releases-948227420.html): `7.4.8` + * Confluence [Long Term Support release](https://confluence.atlassian.com/enterprise/atlassian-enterprise-releases-948227420.html): `7.4.9` * Confluence Platform release: `7.0.5` * Supported Bitbucket Server versions: - * Bitbucket Server [Long Term Support release](https://confluence.atlassian.com/enterprise/atlassian-enterprise-releases-948227420.html): `7.6.4`, `6.10.9` + * Bitbucket Server [Long Term Support release](https://confluence.atlassian.com/enterprise/atlassian-enterprise-releases-948227420.html): `7.6.7`, `6.10.11` * Bitbucket Server Platform release: `7.0.5` +* Supported Crowd versions: + * Crowd [Long Term Support release](https://confluence.atlassian.com/crowd/crowd-release-notes-199094.html): `4.3.0` + ## Support In case of technical questions, issues or problems with DC Apps Performance Toolkit, contact us for support in the [community Slack](http://bit.ly/dcapt_slack) **#data-center-app-performance-toolkit** channel. diff --git a/app/bitbucket.yml b/app/bitbucket.yml index f9a52906e..ce70f7a5c 100644 --- a/app/bitbucket.yml +++ b/app/bitbucket.yml @@ -85,7 +85,7 @@ modules: httpsampler.ignore_failed_embedded_resources: "true" selenium: chromedriver: - version: "90.0.4430.24" # Supports Chrome version 90. You can refer to http://chromedriver.chromium.org/downloads + version: "91.0.4472.101" # Supports Chrome version 91. You can refer to http://chromedriver.chromium.org/downloads reporting: - data-source: sample-labels module: junit-xml diff --git a/app/confluence.yml b/app/confluence.yml index a18ff4aa6..1815f40db 100644 --- a/app/confluence.yml +++ b/app/confluence.yml @@ -109,7 +109,7 @@ modules: httpsampler.ignore_failed_embedded_resources: "true" selenium: chromedriver: - version: "90.0.4430.24" # Supports Chrome version 90. You can refer to http://chromedriver.chromium.org/downloads + version: "91.0.4472.101" # Supports Chrome version 91. You can refer to http://chromedriver.chromium.org/downloads reporting: - data-source: sample-labels module: junit-xml diff --git a/app/crowd.yml b/app/crowd.yml new file mode 100644 index 000000000..33df9c247 --- /dev/null +++ b/app/crowd.yml @@ -0,0 +1,94 @@ +--- +settings: + artifacts-dir: results/crowd/%Y-%m-%d_%H-%M-%S + aggregator: consolidator + verbose: false + env: + application_hostname: test_crowd_instance.atlassian.com # Crowd DC hostname without protocol and port e.g. test-crowd.atlassian.com or localhost + application_protocol: http # http or https + application_port: 80 # 80, 443, 8080, 4990, etc + secure: True # Set False to allow insecure connections, e.g. when using self-signed SSL certificate + application_postfix: # e.g. /crowd in case of url like http://localhost:4990/crowd + admin_login: admin + admin_password: admin + application_name: crowd + application_password: 1111 + load_executor: jmeter + concurrency: 1000 # number of concurrent threads to authenticate random users + test_duration: 45m + + # 1 node scenario parameters + ramp-up: 20s # time to spin all concurrent threads + total_actions_per_hour: 180000 # number of total JMeter actions per hour + + # 2 nodes scenario parameters + # ramp-up: 10s # time to spin all concurrent threads + # total_actions_per_hour: 360000 # number of total JMeter actions per hour + + # 4 nodes scenario parameters + # ramp-up: 5s # time to spin all concurrent threads + # total_actions_per_hour: 720000 # number of total JMeter actions per hour + + JMETER_VERSION: 5.2.1 + LANGUAGE: en_US.utf8 + allow_analytics: Yes # Allow sending basic run analytics to Atlassian. These analytics help us to understand how the tool is being used and help us to continue to invest in this tooling. For more details please see our README. +services: + - module: shellexec + prepare: + - python util/pre_run/environment_checker.py + - python util/data_preparation/crowd_prepare_data.py + - python util/data_preparation/crowd_sync_check.py + shutdown: + - python util/post_run/jmeter_post_check.py + - python util/jtl_convertor/jtls-to-csv.py kpi.jtl + post-process: + - python util/analytics/analytics.py crowd + - python util/post_run/cleanup_results_dir.py +execution: + - scenario: ${load_executor} + executor: ${load_executor} + concurrency: ${concurrency} + hold-for: ${test_duration} + ramp-up: ${ramp-up} +scenarios: + jmeter: + script: jmeter/crowd.jmx + properties: + application_hostname: ${application_hostname} + application_protocol: ${application_protocol} + application_port: ${application_port} + application_postfix: ${application_postfix} + application_name: ${application_name} + application_password: ${application_password} + # Workload model + total_actions_per_hr: ${total_actions_per_hour} +modules: + consolidator: + rtimes-len: 0 # CONFSRVDEV-7631 reduce sampling + percentiles: [] # CONFSRVDEV-7631 disable all percentiles due to Taurus's excessive memory usage + jmeter: + version: ${JMETER_VERSION} + detect-plugins: true + memory-xmx: 8G # allow JMeter to use up to 8G of memory + plugins: + - bzm-parallel=0.4 + - bzm-random-csv=0.6 + - jpgc-casutg=2.5 + - jpgc-dummy=0.2 + - jpgc-ffw=2.0 + - jpgc-fifo=0.2 + - jpgc-functions=2.1 + - jpgc-json=2.6 + - jpgc-perfmon=2.1 + - jpgc-prmctl=0.4 + - jpgc-tst=2.4 + - jpgc-wsc=0.3 + - tilln-sshmon=1.0 + - jpgc-synthesis=2.2 + system-properties: + server.rmi.ssl.disable: true + java.rmi.server.hostname: localhost + httpsampler.ignore_failed_embedded_resources: "true" +reporting: +- data-source: sample-labels + module: junit-xml \ No newline at end of file diff --git a/app/datasets/crowd/examples/users.csv b/app/datasets/crowd/examples/users.csv new file mode 100644 index 000000000..e6a51eefa --- /dev/null +++ b/app/datasets/crowd/examples/users.csv @@ -0,0 +1 @@ +performance_username,password \ No newline at end of file diff --git a/app/jira.yml b/app/jira.yml index 171d85f01..bb6510ecb 100644 --- a/app/jira.yml +++ b/app/jira.yml @@ -113,7 +113,7 @@ modules: httpsampler.ignore_failed_embedded_resources: "true" selenium: chromedriver: - version: "90.0.4430.24" # Supports Chrome version 90. You can refer to http://chromedriver.chromium.org/downloads + version: "91.0.4472.101" # Supports Chrome version 91. You can refer to http://chromedriver.chromium.org/downloads reporting: - data-source: sample-labels module: junit-xml diff --git a/app/jmeter/crowd.jmx b/app/jmeter/crowd.jmx new file mode 100644 index 000000000..9d52f4511 --- /dev/null +++ b/app/jmeter/crowd.jmx @@ -0,0 +1,402 @@ + + + + + + false + true + false + + + + + + + + + + application.hostname + ${__lowercase(${__P(application_hostname, your_crowd_instance)})} + = + + + application.port + ${__P(application_port, 80)} + = + + + application.protocol + ${__P(application_protocol, http)} + = + + + application.postfix + ${__P(application_postfix, )} + = + + + application.name + ${__P(application_name, crowd)} + = + + + application.password + ${__P(application_password, 1111)} + = + + + + + + + + + ${application.hostname} + ${application.port} + ${application.protocol} + + ${application.postfix} + true + 6 + (?i).*${application.hostname}.* + 20000 + + + + + + true + false + + + + + + Origin + ${application.protocol}://${application.hostname}:${application.port} + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + continue + + false + -1 + + 1 + 1 + false + + + true + + + + datasets/crowd/users.csv + UTF-8 + , + username,password + true + false + true + false + + + + + + total_actions_per_hr + ${__P(total_actions_per_hr, 10000)} + = + + + + + + true + 1 + + + + 1 + 0 + 0 + + + + true + + + vars.put("loop_start_time",String.valueOf(System.currentTimeMillis())); + + groovy + + + + + false + true + + + + true + + + + false + <?xml version="1.0" encoding="UTF-8" standalone="yes"?><password><value>${password}</value></password> + = + + + + + + + UTF-8 + ${application.postfix}/rest/usermanagement/1/authentication?username=${username} + POST + true + false + true + false + + + + + + + + + ${application.protocol}://${application.hostname}:${application.port}${application.postfix} + ${application.name} + ${application.password} + + + + + false + + + + + + Accept-Language + en-US,en;q=0.5 + + + Accept + application/xml + + + Content-Type + application/xml; charset=UTF-8 + + + Accept-Encoding + gzip, deflate + + + + + + + <first-name> + + + Assertion.response_data + false + 2 + + + + + + + + + + + + ${application.postfix}/rest/usermanagement/1/user/group/direct?username=${username}&start-index=0&max-results=-1 + GET + true + false + true + false + + + + + + + + + ${application.protocol}://${application.hostname}:${application.port}${application.postfix} + ${application.name} + ${application.password} + + + + + false + + + + + + Accept-Language + en-US,en;q=0.5 + + + Accept + application/xml + + + Content-Type + application/xml; charset=UTF-8 + + + Accept-Encoding + gzip, deflate + + + + + + + group + + + Assertion.response_data + false + 2 + + + + + true + + + log.info("Username: ${vars.get("username")}") + + + groovy + + + + + 1 + 0 + 0 + + + + true + + + // concurrency +def concurrency = ctx.getThreadGroup().getNumThreads() + +// Delays between each action in milli-seconds +def delay_between_transactions = (1000 * 3600) / (vars.get("total_actions_per_hr").toDouble() / concurrency.toDouble()) + +//Sets the pacing length based on the last requests response time. x is the time in ms +def start_time = Long.valueOf(vars.get("loop_start_time")) +def sleep_time = (delay_between_transactions - (System.currentTimeMillis() - start_time)) as int + +log.info("concurrency: ${concurrency}, delay_between_transactions: ${delay_between_transactions}, thread_sleep: ${sleep_time}") + +if ( sleep_time > 0 ) { + return sleep_time +} else { + return 0 +} + + groovy + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + true + true + true + true + true + false + false + true + true + false + true + 0 + true + true + true + true + true + true + true + true + true + + + + true + + + + + diff --git a/app/jmeter/jira.jmx b/app/jmeter/jira.jmx index 13e91b1c8..3fb460094 100644 --- a/app/jmeter/jira.jmx +++ b/app/jmeter/jira.jmx @@ -7015,7 +7015,7 @@ if ( sleep_time > 0 ) { true - + @@ -7101,7 +7101,7 @@ if ( sleep_time > 0 ) { - + @@ -7145,7 +7145,7 @@ if ( sleep_time > 0 ) { - + true @@ -7189,7 +7189,7 @@ if ( sleep_time > 0 ) { - + true @@ -7239,7 +7239,7 @@ if ( sleep_time > 0 ) { true - + @@ -7296,7 +7296,7 @@ if ( sleep_time > 0 ) { - + @@ -7378,7 +7378,7 @@ if ( sleep_time > 0 ) { - + @@ -7460,7 +7460,7 @@ if ( sleep_time > 0 ) { true - + @@ -7535,7 +7535,7 @@ if ( sleep_time > 0 ) { - + @@ -7597,7 +7597,7 @@ if ( sleep_time > 0 ) { - + true @@ -7649,7 +7649,7 @@ if ( sleep_time > 0 ) { - + true @@ -7761,7 +7761,7 @@ if ( sleep_time > 0 ) { - + true @@ -7867,7 +7867,7 @@ if ( sleep_time > 0 ) { true - + @@ -7960,7 +7960,7 @@ if ( sleep_time > 0 ) { - + @@ -8004,7 +8004,7 @@ if ( sleep_time > 0 ) { - + true @@ -8048,7 +8048,7 @@ if ( sleep_time > 0 ) { - + true @@ -8098,7 +8098,7 @@ if ( sleep_time > 0 ) { true - + @@ -8155,7 +8155,7 @@ if ( sleep_time > 0 ) { - + @@ -8237,7 +8237,7 @@ if ( sleep_time > 0 ) { - + @@ -8312,7 +8312,7 @@ if ( sleep_time > 0 ) { - + @@ -8368,7 +8368,7 @@ if ( sleep_time > 0 ) { - + true @@ -8412,7 +8412,7 @@ if ( sleep_time > 0 ) { - + true @@ -8456,7 +8456,7 @@ if ( sleep_time > 0 ) { - + true @@ -8507,7 +8507,7 @@ if ( sleep_time > 0 ) { true - + @@ -8582,7 +8582,7 @@ if ( sleep_time > 0 ) { - + @@ -8644,7 +8644,7 @@ if ( sleep_time > 0 ) { - + @@ -8718,7 +8718,7 @@ if ( sleep_time > 0 ) { true - + true @@ -8834,7 +8834,7 @@ if ( sleep_time > 0 ) { true - + @@ -8875,7 +8875,7 @@ if ( sleep_time > 0 ) { - + true @@ -8919,7 +8919,7 @@ if ( sleep_time > 0 ) { - + @@ -8980,7 +8980,7 @@ if ( sleep_time > 0 ) { - + true @@ -9024,7 +9024,7 @@ if ( sleep_time > 0 ) { - + true @@ -9611,6 +9611,7 @@ if ( sleep_time > 0 ) { 0 true true + true true true true diff --git a/app/jmeter/jsm_agents.jmx b/app/jmeter/jsm_agents.jmx index 71417d780..be4134367 100644 --- a/app/jmeter/jsm_agents.jmx +++ b/app/jmeter/jsm_agents.jmx @@ -7639,7 +7639,7 @@ if ( sleep_time > 0 ) { false - [{"name":"jira.project.centric.navigation.sidebar.load.project","properties":{},"timeDelta":-5064},{"name":"servicedesk.agent.reports.loaded.custom","properties":{"reportId":"204","seriesTypes":"sd.series.type.created.count sd.series.type.resolved.count","sdVersion":"4.13.0","projectId":10035},"timeDelta":-3671},{"name":"servicedesk.page.view.servicedesk.reports","properties":{"sdVersion":"4.13.0","projectId":10035},"timeDelta":-3453},{"name":"browser.metrics.navigation","properties":{"apdex":"0","firstPaint":"1579","isInitial":"true","journeyId":"9073c135-935f-4d53-a0f8-85a1376a51e8","key":"servicedesk.reports.custom","navigationType":"1","readyForUser":"4195","redirectCount":"0","resourceLoadedEnd":"1766","resourceLoadedStart":251.92500000048312,"threshold":"1000","unloadEventStart":"227","unloadEventEnd":"228","fetchStart":"7","domainLookupStart":"7","domainLookupEnd":"7","connectStart":"7","connectEnd":"7","requestStart":"12","responseStart":"162","responseEnd":"193","domLoading":"233","domInteractive":"1832","domContentLoadedEventStart":"1832","domContentLoadedEventEnd":"1899","domComplete":"2219","loadEventStart":"2220","loadEventEnd":"2223","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36","correlationId":"a1fb6e65fe60bb","effectiveType":"4g","downlink":4.35,"rtt":100,"serverDuration":"53","dbConnsTimeInMs":"12","applicationHash":"8c68d8036d917652ef7564456d59d80184b5a77e","resourceTiming":"{\"☠\":[\"2,6z,ca,c1,7m,6z,,6z,6z,6z\",\"2,70,ft,c0,7m,70,,70,70,70\",\"2,70,ew,eq,b6,b6,,7o,7o,7o\",\"3,71,w2,ev,b7,b6,,7p,7p,7p\",\"3,71,vu,ev,b7,b7,,7p,7p,7p\",\"3,71,g1,fw,cb,71,,71,71,71\",\"3,72,j5,ij,ex,72,,72,72,72\",\"3,72,j3,ik,ex,72,,72,72,72\",\"3,72,k5,jd,ft,72,,72,72,72\",\"3,72,k3,jq,g2,72,,72,72,72\",\"2,73,ew,er,b7,b6,,7o,7o,7o\",\"3,73,n7,mz,j8,73,,73,73,73\",\"3,74,11c,119,x5,74,,74,74,74\",\"2,74,11u,11o,y5,74,,74,74,74\",\"3,74,1ab,19w,160,74,,74,74,74\",\"3,74,1a6,19v,160,74,,74,74,74\",\"5,13v,17p,17l,13y,13v,,13v,13v,13v\",\"4,16l,1bt,1bl,180,16l,,16l,16l,16l\",\"3,196,1d2,1cx,19e,196,,196,196,196\",\"5,1kr,1p2,1oy,1l0,1kr,,1kr,1kr,1kr\",\"2,1px,1um,1u4,1ql,1px,,1px,1px,1px\",\"2,1py,1um,1u5,1qm,1py,,1py,1py,1py\",\"2,1py,1v4,1ui,1qn,1py,,1py,1py,1py\",\"3,1py,1v5,1ui,1qo,1py,,1py,1py,1py\",\"3,1pz,1uo,1ud,1qo,1pz,,1pz,1pz,1pz\",\"3,1pz,1v7,1uj,1qs,1pz,,1pz,1pz,1pz\",\"3,1pz,1z1,1ys,1v6,1pz,,1pz,1pz,1pz\",\"5,1wl,20m,20d,1wt,1wl,,1wl,1wl,1wl\",\"5,1zo,23z,23t,1zs,1zo,,1zo,1zo,1zo\",\"5,1zv,23w,23s,202,1zv,,1zv,1zv,1zv\",\"5,20f,251,24o,20z,20f,,20f,20f,20f\",\"5,20h,25h,250,216,20h,,20h,20h,20h\",\"3,246,28n,28e,24j,246,,246,246,246\",\"3,247,28h,286,24k,247,,247,247,247\",\"3,248,28n,287,24k,248,,248,248,248\",\"3,249,28f,286,24k,249,,249,249,249\",\"5,26s,2ar,2ao,271,26s,,26s,26s,26s\",\"5,294,2de,2cz,29a,294,,294,294,294\",\"2,2ea,2iw,2io,2f3,2ea,,2ea,2ea,2ea\",\"3,2ed,2tn,2ix,2f9,2ed,,2ed,2ed,2ed\",\"5,2x7,322,31q,2xe,2x7,,2x7,2x7,2x7\"]}","mark.bigPipe.sidebar-id.start":"[1791]","mark.bigPipe.sidebar-id.end":"[1793]","mark.@grammarly-extension:checkScriptInitStart":"[2113]","mark.@grammarly-extension:checkScriptInitEnd":"[2123]","userTimingRaw":"{\"marks\":{\"bigPipe.sidebar-id.start\":[1791],\"bigPipe.sidebar-id.end\":[1793],\"@grammarly-extension:checkScriptInitStart\":[2113],\"@grammarly-extension:checkScriptInitEnd\":[2123]},\"measures\":{}}","experiments":"[]","dbReadsTimeInMs":"","serverHeadDuration":"undefined","connectionEffectiveType":"4g","connectionDownlink":4.35,"connectionRTT":100},"timeDelta":-3374}] + [{"name":"jira.project.centric.navigation.sidebar.load.project","properties":{},"timeDelta":-5064},{"name":"servicedesk.agent.reports.loaded.custom","properties":{"reportId":"204","seriesTypes":"sd.series.type.created.count sd.series.type.resolved.count","sdVersion":"4.13.0","projectId":10035},"timeDelta":-3671},{"name":"servicedesk.page.view.servicedesk.reports","properties":{"sdVersion":"4.13.0","projectId":10035},"timeDelta":-3453},{"name":"browser.metrics.navigation","properties":{"apdex":"0","firstPaint":"1579","isInitial":"true","journeyId":"9073c135-935f-4d53-a0f8-85a1376a51e8","key":"servicedesk.reports.custom","navigationType":"1","readyForUser":"4195","redirectCount":"0","resourceLoadedEnd":"1766","resourceLoadedStart":251.92500000048312,"threshold":"1000","unloadEventStart":"227","unloadEventEnd":"228","fetchStart":"7","domainLookupStart":"7","domainLookupEnd":"7","connectStart":"7","connectEnd":"7","requestStart":"12","responseStart":"162","responseEnd":"193","domLoading":"233","domInteractive":"1832","domContentLoadedEventStart":"1832","domContentLoadedEventEnd":"1899","domComplete":"2219","loadEventStart":"2220","loadEventEnd":"2223","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36","correlationId":"a1fb6e65fe60bb","effectiveType":"4g","downlink":4.35,"rtt":100,"serverDuration":"53","dbConnsTimeInMs":"12","applicationHash":"8c68d8036d917652ef7564456d59d80184b5a77e","resourceTiming":"{\"˜ \":[\"2,6z,ca,c1,7m,6z,,6z,6z,6z\",\"2,70,ft,c0,7m,70,,70,70,70\",\"2,70,ew,eq,b6,b6,,7o,7o,7o\",\"3,71,w2,ev,b7,b6,,7p,7p,7p\",\"3,71,vu,ev,b7,b7,,7p,7p,7p\",\"3,71,g1,fw,cb,71,,71,71,71\",\"3,72,j5,ij,ex,72,,72,72,72\",\"3,72,j3,ik,ex,72,,72,72,72\",\"3,72,k5,jd,ft,72,,72,72,72\",\"3,72,k3,jq,g2,72,,72,72,72\",\"2,73,ew,er,b7,b6,,7o,7o,7o\",\"3,73,n7,mz,j8,73,,73,73,73\",\"3,74,11c,119,x5,74,,74,74,74\",\"2,74,11u,11o,y5,74,,74,74,74\",\"3,74,1ab,19w,160,74,,74,74,74\",\"3,74,1a6,19v,160,74,,74,74,74\",\"5,13v,17p,17l,13y,13v,,13v,13v,13v\",\"4,16l,1bt,1bl,180,16l,,16l,16l,16l\",\"3,196,1d2,1cx,19e,196,,196,196,196\",\"5,1kr,1p2,1oy,1l0,1kr,,1kr,1kr,1kr\",\"2,1px,1um,1u4,1ql,1px,,1px,1px,1px\",\"2,1py,1um,1u5,1qm,1py,,1py,1py,1py\",\"2,1py,1v4,1ui,1qn,1py,,1py,1py,1py\",\"3,1py,1v5,1ui,1qo,1py,,1py,1py,1py\",\"3,1pz,1uo,1ud,1qo,1pz,,1pz,1pz,1pz\",\"3,1pz,1v7,1uj,1qs,1pz,,1pz,1pz,1pz\",\"3,1pz,1z1,1ys,1v6,1pz,,1pz,1pz,1pz\",\"5,1wl,20m,20d,1wt,1wl,,1wl,1wl,1wl\",\"5,1zo,23z,23t,1zs,1zo,,1zo,1zo,1zo\",\"5,1zv,23w,23s,202,1zv,,1zv,1zv,1zv\",\"5,20f,251,24o,20z,20f,,20f,20f,20f\",\"5,20h,25h,250,216,20h,,20h,20h,20h\",\"3,246,28n,28e,24j,246,,246,246,246\",\"3,247,28h,286,24k,247,,247,247,247\",\"3,248,28n,287,24k,248,,248,248,248\",\"3,249,28f,286,24k,249,,249,249,249\",\"5,26s,2ar,2ao,271,26s,,26s,26s,26s\",\"5,294,2de,2cz,29a,294,,294,294,294\",\"2,2ea,2iw,2io,2f3,2ea,,2ea,2ea,2ea\",\"3,2ed,2tn,2ix,2f9,2ed,,2ed,2ed,2ed\",\"5,2x7,322,31q,2xe,2x7,,2x7,2x7,2x7\"]}","mark.bigPipe.sidebar-id.start":"[1791]","mark.bigPipe.sidebar-id.end":"[1793]","mark.@grammarly-extension:checkScriptInitStart":"[2113]","mark.@grammarly-extension:checkScriptInitEnd":"[2123]","userTimingRaw":"{\"marks\":{\"bigPipe.sidebar-id.start\":[1791],\"bigPipe.sidebar-id.end\":[1793],\"@grammarly-extension:checkScriptInitStart\":[2113],\"@grammarly-extension:checkScriptInitEnd\":[2123]},\"measures\":{}}","experiments":"[]","dbReadsTimeInMs":"","serverHeadDuration":"undefined","connectionEffectiveType":"4g","connectionDownlink":4.35,"connectionRTT":100},"timeDelta":-3374}] = diff --git a/app/jmeter/jsm_customers.jmx b/app/jmeter/jsm_customers.jmx index e8672a492..f9485f5f7 100644 --- a/app/jmeter/jsm_customers.jmx +++ b/app/jmeter/jsm_customers.jmx @@ -866,7 +866,7 @@ if ( sleep_time > 0 ) { false - [{"name":"servicedesk.page.view.requests.global.title.announcement.view.none","properties":{"sdVersion":"4.13.0","projectId":10001},"timeDelta":-688},{"name":"servicedesk.page.view.customerview.allrequests","properties":{"sdVersion":"4.13.0","projectId":10001},"timeDelta":-672},{"name":"browser.metrics.navigation","properties":{"apdex":"0","firstPaint":"265","isInitial":"true","journeyId":"ba5f75b5-0e2e-4e06-bc45-ddd1c9a03cc2","key":"servicedesk.cv.all.requests","navigationType":"0","readyForUser":"52132","redirectCount":"0","resourceLoadedEnd":"262","resourceLoadedStart":200.1600000075996,"threshold":"1000","fetchStart":"11","domainLookupStart":"11","domainLookupEnd":"11","connectStart":"11","connectEnd":"11","requestStart":"18","responseStart":"180","responseEnd":"231","domLoading":"189","domInteractive":"265","domContentLoadedEventStart":"265","domContentLoadedEventEnd":"265","domComplete":"480","loadEventStart":"480","loadEventEnd":"482","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36","effectiveType":"4g","downlink":2.25,"rtt":100,"applicationHash":"8c68d8036d917652ef7564456d59d80184b5a77e","resourceTiming":"{\"☠\":[\"2,5k,5s,5n,5m,5k,,5k,5k,5k\",\"2,5k,5r,5n,5m,5k,,5k,5k,5k\",\"3,6y,7g,71,70,6y,,6y,6y,6y\",\"3,6y,7a,74,71,6y,,6y,6y,6y\",\"4,7c,7c,,,7c,,7c,7c,7c\",\"5,89,cd,cc,8a,89,,89,89,89\",\"3,d7,d9,d8,d8,d7,,d7,d7,d7\",\"5,dd,hg,hg,de,dd,,dd,dd,dd\",\"5,o1,s5,s5,o6,o1,,o1,o1,o1\",\"5,13f8,13jo,13jm,13fk,13f8,,13f8,13f8,13f8\",\"2,13js,13nx,13nw,13jw,13js,,13js,13js,13js\",\"3,13jt,13xq,13pw,13jy,13jt,,13jt,13jt,13jt\",\"5,13y0,1479,1478,13y2,13y0,,13y0,13y0,13y0\"]}","mark.@grammarly-extension:checkScriptInitStart":"[402]","mark.@grammarly-extension:checkScriptInitEnd":"[409]","mark.@grammarly-extension:callExecuteContentScript":"[41420]","mark.@grammarly-extension:initStart":"[41718]","mark.@grammarly-extension:initEnd":"[41735]","userTimingRaw":"{\"marks\":{\"@grammarly-extension:checkScriptInitStart\":[402],\"@grammarly-extension:checkScriptInitEnd\":[409],\"@grammarly-extension:callExecuteContentScript\":[41420],\"@grammarly-extension:initStart\":[41718],\"@grammarly-extension:initEnd\":[41735]},\"measures\":{}}","experiments":"[]","connectionEffectiveType":"4g","connectionDownlink":2.25,"connectionRTT":100},"timeDelta":-655}] + [{"name":"servicedesk.page.view.requests.global.title.announcement.view.none","properties":{"sdVersion":"4.13.0","projectId":10001},"timeDelta":-688},{"name":"servicedesk.page.view.customerview.allrequests","properties":{"sdVersion":"4.13.0","projectId":10001},"timeDelta":-672},{"name":"browser.metrics.navigation","properties":{"apdex":"0","firstPaint":"265","isInitial":"true","journeyId":"ba5f75b5-0e2e-4e06-bc45-ddd1c9a03cc2","key":"servicedesk.cv.all.requests","navigationType":"0","readyForUser":"52132","redirectCount":"0","resourceLoadedEnd":"262","resourceLoadedStart":200.1600000075996,"threshold":"1000","fetchStart":"11","domainLookupStart":"11","domainLookupEnd":"11","connectStart":"11","connectEnd":"11","requestStart":"18","responseStart":"180","responseEnd":"231","domLoading":"189","domInteractive":"265","domContentLoadedEventStart":"265","domContentLoadedEventEnd":"265","domComplete":"480","loadEventStart":"480","loadEventEnd":"482","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36","effectiveType":"4g","downlink":2.25,"rtt":100,"applicationHash":"8c68d8036d917652ef7564456d59d80184b5a77e","resourceTiming":"{\"˜ \":[\"2,5k,5s,5n,5m,5k,,5k,5k,5k\",\"2,5k,5r,5n,5m,5k,,5k,5k,5k\",\"3,6y,7g,71,70,6y,,6y,6y,6y\",\"3,6y,7a,74,71,6y,,6y,6y,6y\",\"4,7c,7c,,,7c,,7c,7c,7c\",\"5,89,cd,cc,8a,89,,89,89,89\",\"3,d7,d9,d8,d8,d7,,d7,d7,d7\",\"5,dd,hg,hg,de,dd,,dd,dd,dd\",\"5,o1,s5,s5,o6,o1,,o1,o1,o1\",\"5,13f8,13jo,13jm,13fk,13f8,,13f8,13f8,13f8\",\"2,13js,13nx,13nw,13jw,13js,,13js,13js,13js\",\"3,13jt,13xq,13pw,13jy,13jt,,13jt,13jt,13jt\",\"5,13y0,1479,1478,13y2,13y0,,13y0,13y0,13y0\"]}","mark.@grammarly-extension:checkScriptInitStart":"[402]","mark.@grammarly-extension:checkScriptInitEnd":"[409]","mark.@grammarly-extension:callExecuteContentScript":"[41420]","mark.@grammarly-extension:initStart":"[41718]","mark.@grammarly-extension:initEnd":"[41735]","userTimingRaw":"{\"marks\":{\"@grammarly-extension:checkScriptInitStart\":[402],\"@grammarly-extension:checkScriptInitEnd\":[409],\"@grammarly-extension:callExecuteContentScript\":[41420],\"@grammarly-extension:initStart\":[41718],\"@grammarly-extension:initEnd\":[41735]},\"measures\":{}}","experiments":"[]","connectionEffectiveType":"4g","connectionDownlink":2.25,"connectionRTT":100},"timeDelta":-655}] = @@ -1038,7 +1038,7 @@ if ( sleep_time > 0 ) { false - [{"name":"servicedesk.customerview.requests.search.filter.changed","properties":{"sdVersion":"4.13.0"},"timeDelta":-2987},{"name":"servicedesk.page.view.requests.global.title.announcement.view.none","properties":{"sdVersion":"4.13.0"},"timeDelta":-2781},{"name":"servicedesk.page.view.customerview.allrequests","properties":{"sdVersion":"4.13.0"},"timeDelta":-2768},{"name":"browser.metrics.navigation","properties":{"apdex":"1","isInitial":"false","journeyId":"eff25cfb-167f-44d9-95b6-07adc3ac84cf","key":"servicedesk.cv.all.requests","readyForUser":"221","threshold":"1000","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36","effectiveType":"4g","downlink":7.7,"rtt":100,"applicationHash":"8c68d8036d917652ef7564456d59d80184b5a77e","resourceTiming":"{\"☠\":[\"5,3,55,54,g,3,,3,3,3\"]}","userTimingRaw":"{\"marks\":{},\"measures\":{}}","experiments":"[]","connectionEffectiveType":"4g","connectionDownlink":7.7,"connectionRTT":100},"timeDelta":-2747}] + [{"name":"servicedesk.customerview.requests.search.filter.changed","properties":{"sdVersion":"4.13.0"},"timeDelta":-2987},{"name":"servicedesk.page.view.requests.global.title.announcement.view.none","properties":{"sdVersion":"4.13.0"},"timeDelta":-2781},{"name":"servicedesk.page.view.customerview.allrequests","properties":{"sdVersion":"4.13.0"},"timeDelta":-2768},{"name":"browser.metrics.navigation","properties":{"apdex":"1","isInitial":"false","journeyId":"eff25cfb-167f-44d9-95b6-07adc3ac84cf","key":"servicedesk.cv.all.requests","readyForUser":"221","threshold":"1000","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36","effectiveType":"4g","downlink":7.7,"rtt":100,"applicationHash":"8c68d8036d917652ef7564456d59d80184b5a77e","resourceTiming":"{\"˜ \":[\"5,3,55,54,g,3,,3,3,3\"]}","userTimingRaw":"{\"marks\":{},\"measures\":{}}","experiments":"[]","connectionEffectiveType":"4g","connectionDownlink":7.7,"connectionRTT":100},"timeDelta":-2747}] = @@ -1181,7 +1181,7 @@ if ( sleep_time > 0 ) { false - [{"name":"servicedesk.customerview.issue.opened","properties":{"isIncident":false,"issueId":10200,"archived":false,"sdVersion":"4.13.0","projectId":10015},"timeDelta":-1821},{"name":"servicedesk.page.view.customerview.requestDetails","properties":{"sdVersion":"4.13.0","projectId":10015},"timeDelta":-1811},{"name":"browser.metrics.navigation","properties":{"apdex":"1","isInitial":"false","journeyId":"eff25cfb-167f-44d9-95b6-07adc3ac84cf","key":"servicedesk.cv.request.details","readyForUser":"220","threshold":"1000","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36","effectiveType":"4g","downlink":10,"rtt":50,"applicationHash":"8c68d8036d917652ef7564456d59d80184b5a77e","resourceTiming":"{\"☠\":[\"5,d,59,58,h,d,,d,d,d\"]}","userTimingRaw":"{\"marks\":{},\"measures\":{}}","experiments":"[]","connectionEffectiveType":"4g","connectionDownlink":10,"connectionRTT":50},"timeDelta":-1802}] + [{"name":"servicedesk.customerview.issue.opened","properties":{"isIncident":false,"issueId":10200,"archived":false,"sdVersion":"4.13.0","projectId":10015},"timeDelta":-1821},{"name":"servicedesk.page.view.customerview.requestDetails","properties":{"sdVersion":"4.13.0","projectId":10015},"timeDelta":-1811},{"name":"browser.metrics.navigation","properties":{"apdex":"1","isInitial":"false","journeyId":"eff25cfb-167f-44d9-95b6-07adc3ac84cf","key":"servicedesk.cv.request.details","readyForUser":"220","threshold":"1000","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36","effectiveType":"4g","downlink":10,"rtt":50,"applicationHash":"8c68d8036d917652ef7564456d59d80184b5a77e","resourceTiming":"{\"˜ \":[\"5,d,59,58,h,d,,d,d,d\"]}","userTimingRaw":"{\"marks\":{},\"measures\":{}}","experiments":"[]","connectionEffectiveType":"4g","connectionDownlink":10,"connectionRTT":50},"timeDelta":-1802}] = @@ -2020,7 +2020,7 @@ if ( sleep_time > 0 ) { false - [{"name":"servicedesk.customerview.smartportal.browse.popular.portals.portal.clicked","properties":{"index":0,"sdVersion":"4.13.0"},"timeDelta":-1193},{"name":"servicedesk.page.view.portal.global.title.announcement.view.none","properties":{"sdVersion":"4.13.0"},"timeDelta":-930},{"name":"servicedesk.page.view.customerview","properties":{"sdVersion":"4.13.0","projectId":10188},"timeDelta":-922},{"name":"browser.metrics.navigation","properties":{"apdex":"0","firstPaint":"297","isInitial":"true","journeyId":"1288b6b6-dc3c-495f-b444-f68ec3b32cb3","key":"servicedesk.cv.portal.landing","navigationType":"0","readyForUser":"5549014","redirectCount":"0","resourceLoadedEnd":"275","resourceLoadedStart":223.40000001713634,"threshold":"1000","unloadEventStart":"207","unloadEventEnd":"207","fetchStart":"2","domainLookupStart":"2","domainLookupEnd":"2","connectStart":"2","connectEnd":"2","requestStart":"5","responseStart":"198","responseEnd":"269","domLoading":"208","domInteractive":"276","domContentLoadedEventStart":"276","domContentLoadedEventEnd":"277","domComplete":"737","loadEventStart":"737","loadEventEnd":"739","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36","effectiveType":"4g","downlink":10,"rtt":50,"applicationHash":"8c68d8036d917652ef7564456d59d80184b5a77e","resourceTiming":"{\"☠\":[\"2,67,67,,,67,,67,67,67\",\"2,67,b0,ax,6r,67,,67,67,67\",\"3,75,7n,76,76,75,,75,75,75\",\"3,75,di,cz,7p,75,,75,75,75\",\"4,7r,7r,,,7r,,7r,7r,7r\",\"5,8w,e6,e5,8x,8w,,8w,8w,8w\",\"3,ev,k6,k4,ex,ev,,ev,ev,ev\",\"5,ke,pq,pp,ki,ke,,ke,ke,ke\",\"5,ow,u7,u7,oy,ow,,ow,ow,ow\",\"5,2k3,2pa,2p9,2k9,2k3,,2k3,2k3,2k3\",\"2,2pd,2ug,2ue,2pe,2pd,,2pd,2pd,2pd\",\"3,2pd,393,2uf,2pf,2pd,,2pd,2pd,2pd\",\"5,3a1,3hj,3hi,3a3,3a1,,3a1,3a1,3a1\",\"4,3hw,3hw,,,3hw,,3hw,3hw,3hw\",\"5,4p7,4uh,4uh,4p8,4p7,,4p7,4p7,4p7\",\"5,zbw,zzm,zzm,zc2,zbw,,zbw,zbw,zbw\",\"5,zzt,105d,105c,100a,zzt,,zzt,zzt,zzt\",\"5,zzu,10e4,10b1,105n,105m,,105m,105m,105m,105k,zzu\",\"2,105g,10an,10al,105i,105g,,105g,105g,105g\",\"3,105h,10e0,109v,105j,105h,,105h,105h,105h\",\"5,10ee,10mk,10mj,10eh,10ee,,10ee,10ee,10ee\",\"4,10nf,10nf,,,10nf,,10nf,10nf,10nf\",\"4,10nh,10sn,10sl,10nj,10nh,,10nh,10nh,10nh\",\"5,13m7,13rb,13ra,13ma,13m7,,13m7,13m7,13m7\",\"5,25qf3,25r6m,25r6l,25qf8,25qf3,,25qf3,25qf3,25qf3\",\"4,25r6y,25r6y,,,25r6y,,25r6y,25r6y,25r6y\",\"5,25tpb,25ug7,25ug6,25tpj,25tpb,,25tpb,25tpb,25tpb\",\"4,25ugi,25ugi,,,25ugi,,25ugi,25ugi,25ugi\",\"5,25v1h,25v5n,25v5m,25v1j,25v1h,,25v1h,25v1h,25v1h\",\"4,25vby,25vby,,,25vby,,25vby,25vby,25vby\",\"5,260by,260zn,260zl,260c0,260by,,260by,260by,260by\",\"5,260zy,2622p,2619f,2614m,2614m,,2614m,2614m,2614m,2614k,260zy\",\"5,2610g,2618i,2618g,2610i,2610g,,2610g,2610g,2610g\",\"4,2619k,2619k,,,2619k,,2619k,2619k,2619k\",\"4,2619m,2619o,2619n,2619n,2619m,,2619m,2619m,2619m\",\"5,262vu,2630x,2630x,262vw,262vu,,262vu,262vu,262vu\",\"4,26t4u,26t4u,,,26t4u,,26t4u,26t4u,26t4u\",\"5,2xuud,2xv69,2xv68,2xuzn,2xuzn,,2xuuk,2xuuk,2xuuk\",\"-1,2xuul,2xv3s,2xv3q,2xuzq,2xuzq,,2xuuo,2xuuo,2xuuo\",\"4,2xv6p,2xv6p,,,2xv6p,,2xv6p,2xv6p,2xv6p\",\"5,2xx2e,2xx6j,2xx6j,2xx2f,2xx2e,,2xx2e,2xx2e,2xx2e\",\"5,2yw6f,2ywgd,2ywgc,2yw92,2yw6f,,2yw6f,2yw6f,2yw6f\",\"4,2ywgp,2ywgp,,,2ywgp,,2ywgp,2ywgp,2ywgp\",\"5,2yzsl,2yzxl,2yzxl,2yzsm,2yzsl,,2yzsl,2yzsl,2yzsl\",\"5,2z5gk,2z5uh,2z5ug,2z5gn,2z5gk,,2z5gk,2z5gk,2z5gk\",\"5,2z5up,2z6b5,2z662,2z60i,2z60h,,2z60h,2z60h,2z60h,2z60f,2z5up\",\"5,2z5uu,2z639,2z638,2z5vg,2z5uu,,2z5uu,2z5uu,2z5uu\",\"4,2z640,2z640,,,2z640,,2z640,2z640,2z640\",\"4,2z642,2z687,2z685,2z644,2z642,,2z642,2z642,2z642\",\"5,2z7o0,2z7sa,2z7s9,2z7o1,2z7o0,,2z7o0,2z7o0,2z7o0\",\"5,38l0q,38lbu,38lbt,38l5p,38l5p,,38l0u,38l0u,38l0u\",\"4,38lc5,38lc5,,,38lc5,,38lc5,38lc5,38lc5\",\"5,38m3t,38m7z,38m7y,38m3u,38m3t,,38m3t,38m3t,38m3t\",\"5,38pd7,38pht,38phr,38pde,38pd7,,38pd7,38pd7,38pd7\",\"2,38phw,38pm6,38pm4,38phy,38phw,,38phw,38phw,38phw\",\"3,38phx,38q9u,38ppl,38phy,38phx,,38phx,38phx,38phx\",\"5,38qa2,38qgx,38qgw,38qa4,38qa2,,38qa2,38qa2,38qa2\",\"4,38qhc,38qhc,,,38qhc,,38qhc,38qhc,38qhc\",\"5,38qhl,38qx8,38qx7,38qhn,38qhl,,38qhl,38qhl,38qhl\",\"5,38s0z,38s7i,38s7h,38s14,38s0z,,38s0z,38s0z,38s0z\",\"4,38s80,38s80,,,38s80,,38s80,38s80,38s80\",\"5,38tvc,38u26,38u25,38tvp,38tvc,,38tvc,38tvc,38tvc\",\"5,38txz,38u24,38u24,38ty0,38txz,,38txz,38txz,38txz\",\"4,38u2i,38u2i,,,38u2i,,38u2i,38u2i,38u2i\",\"5,38xrd,38xxu,38xxt,38xrq,38xrd,,38xrd,38xrd,38xrd\",\"5,38xx6,38y1c,38y1b,38xx7,38xx6,,38xx6,38xx6,38xx6\",\"4,38xy8,38xy8,,,38xy8,,38xy8,38xy8,38xy8\",\"5,38yxg,38z49,38z48,38yxk,38yxg,,38yxg,38yxg,38yxg\",\"5,38z52,38zjn,38zjm,38z54,38z52,,38z52,38z52,38z52\",\"4,38z54,38z54,,,38z54,,38z54,38z54,38z54\",\"5,391wg,3920m,3920m,391wi,391wg,,391wg,391wg,391wg\",\"5,39fu5,39g0i,39g0h,39fuf,39fu5,,39fu5,39fu5,39fu5\",\"4,39g12,39g12,,,39g12,,39g12,39g12,39g12\",\"5,39hh7,39hld,39hld,39hha,39hh7,,39hh7,39hh7,39hh7\",\"5,39k5e,39kc4,39kc3,39k5q,39k5e,,39k5e,39k5e,39k5e\",\"4,39kcl,39kcl,,,39kcl,,39kcl,39kcl,39kcl\",\"5,39lge,39lkl,39lkk,39lgh,39lge,,39lge,39lge,39lge\",\"5,39rpb,39s1s,39s1r,39rpe,39rpb,,39rpb,39rpb,39rpb\",\"5,39s20,39sdn,39sav,39s6f,39s6e,,39s6e,39s6e,39s6e,39s6c,39s20\",\"5,39s27,39sac,39sab,39s2i,39s27,,39s27,39s27,39s27\",\"4,39sb5,39sb5,,,39sb5,,39sb5,39sb5,39sb5\",\"4,39sb7,39sfd,39sfc,39sb9,39sb7,,39sb7,39sb7,39sb7\",\"5,39tai,39tep,39teo,39taj,39tai,,39tai,39tai,39tai\",\"5,3ans0,3anz7,3anz5,3ans9,3ans0,,3ans0,3ans0,3ans0\",\"4,3anzr,3anzr,,,3anzr,,3anzr,3anzr,3anzr\",\"5,3ao01,3aoep,3aoeo,3ao02,3ao01,,3ao01,3ao01,3ao01\",\"5,3aqi8,3aqmz,3aqmy,3aqia,3aqi8,,3aqi8,3aqi8,3aqi8\",\"5,3axfz,3axmn,3axmm,3axgh,3axfz,,3axfz,3axfz,3axfz\"]}","mark.@grammarly-extension:checkScriptInitStart":"[501]","mark.@grammarly-extension:checkScriptInitEnd":"[504]","mark.@grammarly-extension:callExecuteContentScript":"[6613]","mark.@grammarly-extension:initStart":"[6908]","mark.@grammarly-extension:initEnd":"[6930]","mark.@grammarly-extension:gButtonShow":"[7224,3637084,4992992,5455880,5490557]","userTimingRaw":"{\"marks\":{\"@grammarly-extension:checkScriptInitStart\":[501],\"@grammarly-extension:checkScriptInitEnd\":[504],\"@grammarly-extension:callExecuteContentScript\":[6613],\"@grammarly-extension:initStart\":[6908],\"@grammarly-extension:initEnd\":[6930],\"@grammarly-extension:gButtonShow\":[7224,3637084,4992992,5455880,5490557]},\"measures\":{}}","experiments":"[]","connectionEffectiveType":"4g","connectionDownlink":10,"connectionRTT":50},"timeDelta":-913}] + [{"name":"servicedesk.customerview.smartportal.browse.popular.portals.portal.clicked","properties":{"index":0,"sdVersion":"4.13.0"},"timeDelta":-1193},{"name":"servicedesk.page.view.portal.global.title.announcement.view.none","properties":{"sdVersion":"4.13.0"},"timeDelta":-930},{"name":"servicedesk.page.view.customerview","properties":{"sdVersion":"4.13.0","projectId":10188},"timeDelta":-922},{"name":"browser.metrics.navigation","properties":{"apdex":"0","firstPaint":"297","isInitial":"true","journeyId":"1288b6b6-dc3c-495f-b444-f68ec3b32cb3","key":"servicedesk.cv.portal.landing","navigationType":"0","readyForUser":"5549014","redirectCount":"0","resourceLoadedEnd":"275","resourceLoadedStart":223.40000001713634,"threshold":"1000","unloadEventStart":"207","unloadEventEnd":"207","fetchStart":"2","domainLookupStart":"2","domainLookupEnd":"2","connectStart":"2","connectEnd":"2","requestStart":"5","responseStart":"198","responseEnd":"269","domLoading":"208","domInteractive":"276","domContentLoadedEventStart":"276","domContentLoadedEventEnd":"277","domComplete":"737","loadEventStart":"737","loadEventEnd":"739","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36","effectiveType":"4g","downlink":10,"rtt":50,"applicationHash":"8c68d8036d917652ef7564456d59d80184b5a77e","resourceTiming":"{\"˜ \":[\"2,67,67,,,67,,67,67,67\",\"2,67,b0,ax,6r,67,,67,67,67\",\"3,75,7n,76,76,75,,75,75,75\",\"3,75,di,cz,7p,75,,75,75,75\",\"4,7r,7r,,,7r,,7r,7r,7r\",\"5,8w,e6,e5,8x,8w,,8w,8w,8w\",\"3,ev,k6,k4,ex,ev,,ev,ev,ev\",\"5,ke,pq,pp,ki,ke,,ke,ke,ke\",\"5,ow,u7,u7,oy,ow,,ow,ow,ow\",\"5,2k3,2pa,2p9,2k9,2k3,,2k3,2k3,2k3\",\"2,2pd,2ug,2ue,2pe,2pd,,2pd,2pd,2pd\",\"3,2pd,393,2uf,2pf,2pd,,2pd,2pd,2pd\",\"5,3a1,3hj,3hi,3a3,3a1,,3a1,3a1,3a1\",\"4,3hw,3hw,,,3hw,,3hw,3hw,3hw\",\"5,4p7,4uh,4uh,4p8,4p7,,4p7,4p7,4p7\",\"5,zbw,zzm,zzm,zc2,zbw,,zbw,zbw,zbw\",\"5,zzt,105d,105c,100a,zzt,,zzt,zzt,zzt\",\"5,zzu,10e4,10b1,105n,105m,,105m,105m,105m,105k,zzu\",\"2,105g,10an,10al,105i,105g,,105g,105g,105g\",\"3,105h,10e0,109v,105j,105h,,105h,105h,105h\",\"5,10ee,10mk,10mj,10eh,10ee,,10ee,10ee,10ee\",\"4,10nf,10nf,,,10nf,,10nf,10nf,10nf\",\"4,10nh,10sn,10sl,10nj,10nh,,10nh,10nh,10nh\",\"5,13m7,13rb,13ra,13ma,13m7,,13m7,13m7,13m7\",\"5,25qf3,25r6m,25r6l,25qf8,25qf3,,25qf3,25qf3,25qf3\",\"4,25r6y,25r6y,,,25r6y,,25r6y,25r6y,25r6y\",\"5,25tpb,25ug7,25ug6,25tpj,25tpb,,25tpb,25tpb,25tpb\",\"4,25ugi,25ugi,,,25ugi,,25ugi,25ugi,25ugi\",\"5,25v1h,25v5n,25v5m,25v1j,25v1h,,25v1h,25v1h,25v1h\",\"4,25vby,25vby,,,25vby,,25vby,25vby,25vby\",\"5,260by,260zn,260zl,260c0,260by,,260by,260by,260by\",\"5,260zy,2622p,2619f,2614m,2614m,,2614m,2614m,2614m,2614k,260zy\",\"5,2610g,2618i,2618g,2610i,2610g,,2610g,2610g,2610g\",\"4,2619k,2619k,,,2619k,,2619k,2619k,2619k\",\"4,2619m,2619o,2619n,2619n,2619m,,2619m,2619m,2619m\",\"5,262vu,2630x,2630x,262vw,262vu,,262vu,262vu,262vu\",\"4,26t4u,26t4u,,,26t4u,,26t4u,26t4u,26t4u\",\"5,2xuud,2xv69,2xv68,2xuzn,2xuzn,,2xuuk,2xuuk,2xuuk\",\"-1,2xuul,2xv3s,2xv3q,2xuzq,2xuzq,,2xuuo,2xuuo,2xuuo\",\"4,2xv6p,2xv6p,,,2xv6p,,2xv6p,2xv6p,2xv6p\",\"5,2xx2e,2xx6j,2xx6j,2xx2f,2xx2e,,2xx2e,2xx2e,2xx2e\",\"5,2yw6f,2ywgd,2ywgc,2yw92,2yw6f,,2yw6f,2yw6f,2yw6f\",\"4,2ywgp,2ywgp,,,2ywgp,,2ywgp,2ywgp,2ywgp\",\"5,2yzsl,2yzxl,2yzxl,2yzsm,2yzsl,,2yzsl,2yzsl,2yzsl\",\"5,2z5gk,2z5uh,2z5ug,2z5gn,2z5gk,,2z5gk,2z5gk,2z5gk\",\"5,2z5up,2z6b5,2z662,2z60i,2z60h,,2z60h,2z60h,2z60h,2z60f,2z5up\",\"5,2z5uu,2z639,2z638,2z5vg,2z5uu,,2z5uu,2z5uu,2z5uu\",\"4,2z640,2z640,,,2z640,,2z640,2z640,2z640\",\"4,2z642,2z687,2z685,2z644,2z642,,2z642,2z642,2z642\",\"5,2z7o0,2z7sa,2z7s9,2z7o1,2z7o0,,2z7o0,2z7o0,2z7o0\",\"5,38l0q,38lbu,38lbt,38l5p,38l5p,,38l0u,38l0u,38l0u\",\"4,38lc5,38lc5,,,38lc5,,38lc5,38lc5,38lc5\",\"5,38m3t,38m7z,38m7y,38m3u,38m3t,,38m3t,38m3t,38m3t\",\"5,38pd7,38pht,38phr,38pde,38pd7,,38pd7,38pd7,38pd7\",\"2,38phw,38pm6,38pm4,38phy,38phw,,38phw,38phw,38phw\",\"3,38phx,38q9u,38ppl,38phy,38phx,,38phx,38phx,38phx\",\"5,38qa2,38qgx,38qgw,38qa4,38qa2,,38qa2,38qa2,38qa2\",\"4,38qhc,38qhc,,,38qhc,,38qhc,38qhc,38qhc\",\"5,38qhl,38qx8,38qx7,38qhn,38qhl,,38qhl,38qhl,38qhl\",\"5,38s0z,38s7i,38s7h,38s14,38s0z,,38s0z,38s0z,38s0z\",\"4,38s80,38s80,,,38s80,,38s80,38s80,38s80\",\"5,38tvc,38u26,38u25,38tvp,38tvc,,38tvc,38tvc,38tvc\",\"5,38txz,38u24,38u24,38ty0,38txz,,38txz,38txz,38txz\",\"4,38u2i,38u2i,,,38u2i,,38u2i,38u2i,38u2i\",\"5,38xrd,38xxu,38xxt,38xrq,38xrd,,38xrd,38xrd,38xrd\",\"5,38xx6,38y1c,38y1b,38xx7,38xx6,,38xx6,38xx6,38xx6\",\"4,38xy8,38xy8,,,38xy8,,38xy8,38xy8,38xy8\",\"5,38yxg,38z49,38z48,38yxk,38yxg,,38yxg,38yxg,38yxg\",\"5,38z52,38zjn,38zjm,38z54,38z52,,38z52,38z52,38z52\",\"4,38z54,38z54,,,38z54,,38z54,38z54,38z54\",\"5,391wg,3920m,3920m,391wi,391wg,,391wg,391wg,391wg\",\"5,39fu5,39g0i,39g0h,39fuf,39fu5,,39fu5,39fu5,39fu5\",\"4,39g12,39g12,,,39g12,,39g12,39g12,39g12\",\"5,39hh7,39hld,39hld,39hha,39hh7,,39hh7,39hh7,39hh7\",\"5,39k5e,39kc4,39kc3,39k5q,39k5e,,39k5e,39k5e,39k5e\",\"4,39kcl,39kcl,,,39kcl,,39kcl,39kcl,39kcl\",\"5,39lge,39lkl,39lkk,39lgh,39lge,,39lge,39lge,39lge\",\"5,39rpb,39s1s,39s1r,39rpe,39rpb,,39rpb,39rpb,39rpb\",\"5,39s20,39sdn,39sav,39s6f,39s6e,,39s6e,39s6e,39s6e,39s6c,39s20\",\"5,39s27,39sac,39sab,39s2i,39s27,,39s27,39s27,39s27\",\"4,39sb5,39sb5,,,39sb5,,39sb5,39sb5,39sb5\",\"4,39sb7,39sfd,39sfc,39sb9,39sb7,,39sb7,39sb7,39sb7\",\"5,39tai,39tep,39teo,39taj,39tai,,39tai,39tai,39tai\",\"5,3ans0,3anz7,3anz5,3ans9,3ans0,,3ans0,3ans0,3ans0\",\"4,3anzr,3anzr,,,3anzr,,3anzr,3anzr,3anzr\",\"5,3ao01,3aoep,3aoeo,3ao02,3ao01,,3ao01,3ao01,3ao01\",\"5,3aqi8,3aqmz,3aqmy,3aqia,3aqi8,,3aqi8,3aqi8,3aqi8\",\"5,3axfz,3axmn,3axmm,3axgh,3axfz,,3axfz,3axfz,3axfz\"]}","mark.@grammarly-extension:checkScriptInitStart":"[501]","mark.@grammarly-extension:checkScriptInitEnd":"[504]","mark.@grammarly-extension:callExecuteContentScript":"[6613]","mark.@grammarly-extension:initStart":"[6908]","mark.@grammarly-extension:initEnd":"[6930]","mark.@grammarly-extension:gButtonShow":"[7224,3637084,4992992,5455880,5490557]","userTimingRaw":"{\"marks\":{\"@grammarly-extension:checkScriptInitStart\":[501],\"@grammarly-extension:checkScriptInitEnd\":[504],\"@grammarly-extension:callExecuteContentScript\":[6613],\"@grammarly-extension:initStart\":[6908],\"@grammarly-extension:initEnd\":[6930],\"@grammarly-extension:gButtonShow\":[7224,3637084,4992992,5455880,5490557]},\"measures\":{}}","experiments":"[]","connectionEffectiveType":"4g","connectionDownlink":10,"connectionRTT":50},"timeDelta":-913}] = diff --git a/app/locustio/common_utils.py b/app/locustio/common_utils.py index 060be0383..b7adcb31b 100644 --- a/app/locustio/common_utils.py +++ b/app/locustio/common_utils.py @@ -55,11 +55,15 @@ "Accept": "application/json, text/javascript, */*; q=0.01" } -JIRA_API_URL = '/rest/api/2/serverInfo' -CONFLUENCE_API_URL = '/rest/api/user/anonymous' +JIRA_API_URL = '/' +CONFLUENCE_API_URL = '/' +JIRA_TOKEN_PATTERN = r'name="atlassian-token" content="(.+?)">' +CONFLUENCE_TOKEN_PATTERN = r'"ajs-atl-token" content="(.+?)"' JIRA = 'jira' JSM = 'jsm' +TYPE_AGENT = 'agent' +TYPE_CUSTOMER = 'customer' CONFLUENCE = 'confluence' jira_action_time = 3600 / int((JIRA_SETTINGS.total_actions_per_hour) / int(JIRA_SETTINGS.concurrency)) @@ -314,22 +318,38 @@ def wrapper(*args, **kwargs): session_user_name = locust.session_data_storage["username"] session_user_password = locust.session_data_storage["password"] app = locust.session_data_storage['app'] + app_type = locust.session_data_storage.get('app_type', None) + token_pattern = None - if app == JIRA or app == JSM: + # Jira or JSM Agent - redefine token value + if app == JIRA or (app == JSM and app_type == TYPE_AGENT): url = JIRA_API_URL + token_pattern = JIRA_TOKEN_PATTERN + # JSM Customer + elif app == JSM and app_type == TYPE_CUSTOMER: + url = JIRA_API_URL + # Confluence - redefine token value elif app == CONFLUENCE: url = CONFLUENCE_API_URL + token_pattern = CONFLUENCE_TOKEN_PATTERN else: raise Exception(f'The "{app}" application type is not known.') - locust.client.cookies.clear() - locust.get(url, auth=(username, password), catch_response=True) # send requests by the specific user + def do_login(usr, pwd): + locust.client.cookies.clear() + r = locust.get(url, auth=(usr, pwd), catch_response=True) + if token_pattern: + content = r.content.decode('utf-8') + token = fetch_by_re(token_pattern, content) + locust.session_data_storage["token"] = token + + # send requests by the specific user + do_login(usr=username, pwd=password) func(*args, **kwargs) - locust.client.cookies.clear() - locust.get(url, auth=(session_user_name, session_user_password), - catch_response=True) # send requests by the session user + # send requests by the session user + do_login(usr=session_user_name, pwd=session_user_password) else: raise SystemExit(f"There is no 'locust' object in the '{func.__name__}' function.") diff --git a/app/locustio/confluence/http_actions.py b/app/locustio/confluence/http_actions.py index e82c76953..b2dd90bb3 100644 --- a/app/locustio/confluence/http_actions.py +++ b/app/locustio/confluence/http_actions.py @@ -5,7 +5,7 @@ TEXT_HEADERS, NO_TOKEN_HEADERS, JSON_HEADERS, RESOURCE_HEADERS, generate_random_string, init_logger, \ raise_if_login_failed from locustio.confluence.requests_params import confluence_datasets, Login, ViewPage, ViewDashboard, ViewBlog, \ - CreateBlog, CreateEditPage, UploadAttachments, LikePage + CreateBlog, CreateEditPage, UploadAttachments, LikePage, CommentPage, ViewAttachment from util.conf import CONFLUENCE_SETTINGS import uuid @@ -28,126 +28,203 @@ def login_and_view_dashboard(locust): login_body = params.login_body login_body['os_username'] = username login_body['os_password'] = password - locust.post('/dologin.action', login_body, TEXT_HEADERS, catch_response=True) + + # 10 dologin.action + locust.post('/dologin.action', + login_body, + TEXT_HEADERS, + catch_response=True) + r = locust.get(url='/', catch_response=True) content = r.content.decode('utf-8') + if 'Log Out' not in content: logger.error(f'Login with {username}, {password} failed: {content}') assert 'Log Out' in content, 'User authentication failed.' logger.locust_info(f'User {username} is successfully logged in') keyboard_hash = fetch_by_re(params.keyboard_hash_re, content) build_number = fetch_by_re(params.build_number_re, content) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("010"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.get('/rest/mywork/latest/status/notification/count', catch_response=True) + token = fetch_by_re(params.atl_token_pattern, content) + + # 20 index.action + locust.get('/index.action', catch_response=True) + + # 30 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("30"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 40 rest/shortcuts/latest/shortcuts/{ajs-build-number}/{ajs-keyboardshortcut-hash} locust.get(f'/rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash}', catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("025"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.get(f'/rest/experimental/search?cql=type=space%20and%20space.type=favourite%20order%20by%20favourite' - f'%20desc&expand=space.icon&limit=100&_={timestamp_int()}', catch_response=True) + + # 50 rest/mywork/latest/status/notification/count + locust.get('/rest/mywork/latest/status/notification/count', catch_response=True) + + # 60 rest/dashboardmacros/1.0/updates locust.get('/rest/dashboardmacros/1.0/updates?maxResults=40&tab=all&showProfilePic=true&labels=' - '&spaces=&users=&types=&category=&spaceKey=', catch_response=True) + '&spaces=&users=&types=&category=&spaceKey=', + catch_response=True) + + # 70 rest/experimental/search + locust.get(f'/rest/experimental/search?cql=type=space%20and%20space.type=favourite%20order%20by%20' + f'favourite%20desc&expand=space.icon&limit=100&_={timestamp_int()}', + catch_response=True) + + # 80 rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("80"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 90 rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("90"), + headers=RESOURCE_HEADERS, + catch_response=True) locust.session_data_storage['build_number'] = build_number locust.session_data_storage['keyboard_hash'] = keyboard_hash locust.session_data_storage['username'] = user[0] locust.session_data_storage['password'] = user[1] + locust.session_data_storage['token'] = token -def view_page_and_tree(locust): +@confluence_measure('locust_view_page') +def view_page(locust): raise_if_login_failed(locust) params = ViewPage() page = random.choice(confluence_dataset["pages"]) page_id = page[0] - @confluence_measure('locust_view_page:open_page') - def view_page(): - r = locust.get(f'/pages/viewpage.action?pageId={page_id}', catch_response=True) - content = r.content.decode('utf-8') - if 'Created by' not in content or 'Save for later' not in content: - logger.error(f'Fail to open page {page_id}: {content}') - assert 'Created by' in content and 'Save for later' in content, 'Could not open page.' - parent_page_id = fetch_by_re(params.parent_page_id_re, content) - parsed_page_id = fetch_by_re(params.page_id_re, content) - space_key = fetch_by_re(params.space_key_re, content) - tree_request_id = fetch_by_re(params.tree_result_id_re, content) - has_no_root = fetch_by_re(params.has_no_root_re, content) - root_page_id = fetch_by_re(params.root_page_id_re, content) - atl_token_view_issue = fetch_by_re(params.atl_token_view_issue_re, content) - editable = fetch_by_re(params.editable_re, content) - ancestor_ids = re.findall(params.ancestor_ids_re, content) - - ancestor_str = 'ancestors=' - for ancestor in ancestor_ids: - ancestor_str = ancestor_str + str(ancestor) + '&' - - locust.session_data_storage['page_id'] = parsed_page_id - locust.session_data_storage['has_no_root'] = has_no_root - locust.session_data_storage['tree_request_id'] = tree_request_id - locust.session_data_storage['root_page_id'] = root_page_id - locust.session_data_storage['ancestors'] = ancestor_str - locust.session_data_storage['space_key'] = space_key - locust.session_data_storage['editable'] = editable - locust.session_data_storage['atl_token_view_issue'] = atl_token_view_issue + # 100 pages/viewpage.action + r = locust.get(f'/pages/viewpage.action?pageId={page_id}', catch_response=True) - locust.get('/rest/helptips/1.0/tips', catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("110"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.get(f'/rest/likes/1.0/content/{parsed_page_id}/likes?commentLikes=true&_={timestamp_int()}', - catch_response=True) - locust.get(f'/rest/highlighting/1.0/panel-items?pageId={parsed_page_id}&_={timestamp_int()}', - catch_response=True) - locust.get(f'/rest/mywork/latest/status/notification/count?pageId={parsed_page_id}&_={timestamp_int()}', + content = r.content.decode('utf-8') + if 'Created by' not in content or 'Save for later' not in content: + logger.error(f'Fail to open page {page_id}: {content}') + assert 'Created by' in content and 'Save for later' in content, 'Could not open page.' + parent_page_id = fetch_by_re(params.parent_page_id_re, content) + parsed_page_id = fetch_by_re(params.page_id_re, content) + space_key = fetch_by_re(params.space_key_re, content) + tree_request_id = fetch_by_re(params.tree_result_id_re, content) + has_no_root = fetch_by_re(params.has_no_root_re, content) + root_page_id = fetch_by_re(params.root_page_id_re, content) + + editable = fetch_by_re(params.editable_re, content) + ancestor_ids = re.findall(params.ancestor_ids_re, content) + + ancestor_str = 'ancestors=' + for ancestor in ancestor_ids: + ancestor_str = ancestor_str + str(ancestor) + '&' + + locust.session_data_storage['page_id'] = parsed_page_id + locust.session_data_storage['has_no_root'] = has_no_root + locust.session_data_storage['tree_request_id'] = tree_request_id + locust.session_data_storage['root_page_id'] = root_page_id + locust.session_data_storage['ancestors'] = ancestor_str + locust.session_data_storage['space_key'] = space_key + locust.session_data_storage['editable'] = editable + + # 110 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("110"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 120 rest/helptips/1.0/tips + locust.get('/rest/helptips/1.0/tips', catch_response=True) + + # 130 rest/inlinecomments/1.0/comments + r = locust.get(f'/rest/inlinecomments/1.0/comments' + f'?containerId={parsed_page_id}' + f'&_={timestamp_int()}', catch_response=True) - r = locust.get(f'/rest/inlinecomments/1.0/comments?containerId={parsed_page_id}&_={timestamp_int()}', - catch_response=True) - content = r.content.decode('utf-8') - if 'authorDisplayName' not in content and '[]' not in content: - logger.error(f'Could not open comments for page {parsed_page_id}: {content}') - assert 'authorDisplayName' in content or '[]' in content, 'Could not open comments for page.' - locust.get(f'/plugins/editor-loader/editor.action?parentPageId={parent_page_id}&pageId={parsed_page_id}' - f'&spaceKey={space_key}&atl_after_login_redirect=/pages/viewpage.action' - f'&timeout=12000&_={timestamp_int()}', catch_response=True) - locust.get(f'/rest/watch-button/1.0/watchState/{parsed_page_id}?_={timestamp_int()}', - catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("145"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("150"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("155"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("160"), - headers=RESOURCE_HEADERS, catch_response=True) - - @confluence_measure('locust_view_page:view_page_tree') - def view_page_tree(): - tree_request_id = locust.session_data_storage['tree_request_id'].replace('&', '&') - # if postfix is set, need to trim it from the tree_request_id to avoid duplication - if tree_request_id.startswith(CONFLUENCE_SETTINGS.postfix): - tree_request_id = tree_request_id[len(CONFLUENCE_SETTINGS.postfix):] - ancestors = locust.session_data_storage['ancestors'] - root_page_id = locust.session_data_storage['root_page_id'] - viewed_page_id = locust.session_data_storage['page_id'] - space_key = locust.session_data_storage['space_key'] - r = '' - # Page has parent - if locust.session_data_storage['has_no_root'] == 'false': - request = f"{tree_request_id}&hasRoot=true&pageId={root_page_id}&treeId=0&startDepth=0&mobile=false" \ - f"&{ancestors}treePageId={viewed_page_id}&_={timestamp_int()}" - r = locust.get(f'{request}', catch_response=True) - # Page does not have parent - elif locust.session_data_storage['has_no_root'] == 'true': - request = f"{tree_request_id}&hasRoot=false&spaceKey={space_key}&treeId=0&startDepth=0&mobile=false" \ - f"&{ancestors}treePageId={viewed_page_id}&_={timestamp_int()}" - r = locust.get(f'{request}', catch_response=True) - content = r.content.decode('utf-8') - if 'plugin_pagetree_children_span' not in content or 'plugin_pagetree_children_list' not in content: - logger.error(f'Could not view page tree: {content}') - assert 'plugin_pagetree_children_span' in content and 'plugin_pagetree_children_list' in content, \ - 'Could not view page tree.' + content = r.content.decode('utf-8') + if 'authorDisplayName' not in content and '[]' not in content: + logger.error(f'Could not open comments for page {parsed_page_id}: {content}') + assert 'authorDisplayName' in content or '[]' in content, 'Could not open comments for page.' + + # 140 rest/shortcuts/latest/shortcuts/{ajs-build-number}/{ajs-keyboardshortcut-hash} + locust.get(f'/rest/shortcuts/latest/shortcuts/' + f'{locust.session_data_storage["build_number"]}/' + f'{locust.session_data_storage["keyboard_hash"]}', + catch_response=True) - view_page() - view_page_tree() + # 150 plugins/pagetree/naturalchildren.action + locust.get(f'/plugins/pagetree/naturalchildren.action' + f'?decorator=none' + f'&expandCurrent=true' + f'&mobile=false' + f'&sort=position' + f'&reverse=false' + f'&spaceKey={space_key}' + f'&treeId=0' + f'&hasRoot=false' + f'&startDepth=0' + f'&disableLinks=false' + f'&placement=sidebar' + f'&excerpt=false' + f'&ancestors={parent_page_id}' + f'&treePageId={parsed_page_id}' + f'&_={timestamp_int()}', + catch_response=True) + + # 160 rest/likes/1.0/content/{page_id}/likes + locust.get(f'/rest/likes/1.0/content/{parsed_page_id}/likes' + f'?commentLikes=true' + f'&_={timestamp_int()}', + catch_response=True) + + # 170 rest/highlighting/1.0/panel-items + locust.get(f'/rest/highlighting/1.0/panel-items' + f'?pageId={parsed_page_id}' + f'&_={timestamp_int()}', + catch_response=True) + + # 180 rest/mywork/latest/status/notification/count + locust.get(f'/rest/mywork/latest/status/notification/count' + f'?pageId={parsed_page_id}' + f'&_={timestamp_int()}', + catch_response=True) + + # 190 rest/watch-button/1.0/watchState/${page_id} + locust.get(f'/rest/watch-button/1.0/watchState/{parsed_page_id}' + f'?_={timestamp_int()}', + catch_response=True) + + # 200 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("200"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 210 plugins/editor-loader/editor.action + locust.get(f'/plugins/editor-loader/editor.action' + f'?parentPageId={parent_page_id}' + f'&pageId={parsed_page_id}' + f'&spaceKey={space_key}' + f'&atl_after_login_redirect=/pages/viewpage.action' + f'&timeout=12000&_={timestamp_int()}', + catch_response=True) + + # 220 rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("220"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 230 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("230"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 240 plugins/macrobrowser/browse-macros.action + locust.get('/plugins/macrobrowser/browse-macros.action' + '?macroMetadataClientCacheKey=1618567304880' + '&detailed=false', + catch_response=True) @confluence_measure('locust_view_dashboard') @@ -155,7 +232,9 @@ def view_dashboard(locust): raise_if_login_failed(locust) params = ViewDashboard() + # 270 index.action r = locust.get('/index.action', catch_response=True) + content = r.content.decode('utf-8') keyboard_hash = fetch_by_re(params.keyboard_hash_re, content) build_number = fetch_by_re(params.build_number_re, content) @@ -163,19 +242,50 @@ def view_dashboard(locust): logger.error(f'Could not view dashboard: {content}') assert 'quick-search' in content and 'Log Out' in content, 'Could not view dashboard.' - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("205"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.get('/rest/mywork/latest/status/notification/count', catch_response=True) + # 280 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("280"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 290 rest/shortcuts/latest/shortcuts/${ajs-build-number}/${ajs-keyboardshortcut-hash} locust.get(f'/rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash}', catch_response=True) - locust.get(f'/rest/experimental/search?cql=type=space%20and%20space.type=favourite%20order%20by%20' - f'favourite%20desc&expand=space.icon&limit=100&_={timestamp_int()}', catch_response=True) - r = locust.get('/rest/dashboardmacros/1.0/updates?maxResults=40&tab=all&showProfilePic=true&labels=' - '&spaces=&users=&types=&category=&spaceKey=', catch_response=True) + + # 300 rest/mywork/latest/status/notification/count + locust.get('/rest/mywork/latest/status/notification/count', catch_response=True) + + # 310 rest/dashboardmacros/1.0/updates + r = locust.get('/rest/dashboardmacros/1.0/updates' + '?maxResults=40' + '&tab=all' + '&showProfilePic=true&' + 'labels=' + '&spaces=' + '&users=' + '&types=' + '&category=' + '&spaceKey=', + catch_response=True) + content = r.content.decode('utf-8') if 'changeSets' not in content: logger.error(f'Could not view dashboard macros: {content}') assert 'changeSets' in content, 'Could not view dashboard macros.' + # 320 rest/experimental/search + locust.get(f'/rest/experimental/search' + f'?cql=type=space%20and%20space.type=favourite%20order%20by%20favourite%20desc' + f'&expand=space.icon' + f'&limit=100' + f'&_={timestamp_int()}', + catch_response=True) + + # 330 rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("330"), + headers=RESOURCE_HEADERS, + catch_response=True) + @confluence_measure('locust_view_blog') def view_blog(locust): @@ -184,50 +294,115 @@ def view_blog(locust): blog = random.choice(confluence_dataset["blogs"]) blog_id = blog[0] - r = locust.get(f'/pages/viewpage.action?pageId={blog_id}', catch_response=True) + # 340 pages/viewpage.action + r = locust.get(f'/pages/viewpage.action' + f'?pageId={blog_id}', + catch_response=True) + content = r.content.decode('utf-8') if 'Created by' not in content or 'Save for later' not in content: logger.error(f'Fail to open blog {blog_id}: {content}') assert 'Created by' in content and 'Save for later' in content, 'Could not view blog.' + keyboard_hash = fetch_by_re(params.keyboard_hash_re, content) + build_number = fetch_by_re(params.build_number_re, content) parent_page_id = fetch_by_re(params.parent_page_id_re, content) - parsed_blog_id = fetch_by_re(params.page_id_re, content) space_key = fetch_by_re(params.space_key_re, content) + # 350 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("350"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 360 rest/helptips/1.0/tips locust.get('/rest/helptips/1.0/tips', catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("310"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.get(f'/rest/likes/1.0/content/{parsed_blog_id}/likes?commentLikes=true&_={timestamp_int()}', - catch_response=True) - locust.get(f'/rest/highlighting/1.0/panel-items?pageId={parsed_blog_id}&_={timestamp_int()}', - catch_response=True) - locust.get(f'/rest/mywork/latest/status/notification/count?pageId={parsed_blog_id}&_={timestamp_int()}', - catch_response=True) - r = locust.get(f'/rest/inlinecomments/1.0/comments?containerId={parsed_blog_id}&_={timestamp_int()}', + + # 370 rest/inlinecomments/1.0/comments + r = locust.get(f'/rest/inlinecomments/1.0/comments' + f'?containerId={blog_id}' + f'&_={timestamp_int()}', catch_response=True) content = r.content.decode('utf-8') if 'authorDisplayName' not in content and '[]' not in content: - logger.error(f'Could not open comments for page {parsed_blog_id}: {content}') + logger.error(f'Could not open comments for page {blog_id}: {content}') assert 'authorDisplayName' in content or '[]' in content, 'Could not open comments for page.' - r = locust.get(f'/plugins/editor-loader/editor.action?parentPageId={parent_page_id}&pageId={parsed_blog_id}' - f'&spaceKey={space_key}&atl_after_login_redirect=/pages/viewpage.action' - f'&timeout=12000&_={timestamp_int()}', catch_response=True) + # 380 rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash} + locust.get(f'/rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash}' + f'?_={timestamp_int()}', + catch_response=True) + + # 390 rest/likes/1.0/content/{blog_id}/likes + locust.get(f'/rest/likes/1.0/content/{blog_id}/likes' + f'?commentLikes=true' + f'&_={timestamp_int()}', + catch_response=True) + + # 400 rest/highlighting/1.0/panel-items + locust.get(f'/rest/highlighting/1.0/panel-items' + f'?pageId={blog_id}' + f'&_={timestamp_int()}', + catch_response=True) + + # 410 rest/mywork/latest/status/notification/count + locust.get(f'/rest/mywork/latest/status/notification/count' + f'?pageId={blog_id}' + f'&_={timestamp_int()}', + catch_response=True) + + # 420 rest/watch-button/1.0/watchState/${ajs-page-id} + locust.get(f'/rest/watch-button/1.0/watchState/{blog_id}' + f'?_={timestamp_int()}', + catch_response=True) + + # 430 rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("430"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 440 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("440"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 450 rest/mywork/latest/status/notification/count + locust.get(f'/rest/mywork/latest/status/notification/count' + f'?_={timestamp_int()}', + catch_response=True) + + # 460 /rest/quickreload/latest/{blog_id} + locust.get(f'/rest/quickreload/latest/{blog_id}' + f'?since={timestamp_int()}' + f'&_={timestamp_int()}', + catch_response=True) + + # 470 plugins/editor-loader/editor.action + r = locust.get(f'/plugins/editor-loader/editor.action' + f'?parentPageId={parent_page_id}' + f'&pageId={blog_id}' + f'&spaceKey={space_key}' + f'&atl_after_login_redirect=/pages/viewpage.action' + f'&timeout=12000&_={timestamp_int()}', + catch_response=True) + content = r.content.decode('utf-8') if 'draftId' not in content: - logger.error(f'Could not open editor for blog {parsed_blog_id}: {content}') + logger.error(f'Could not open editor for blog {blog_id}: {content}') assert 'draftId' in content, 'Could not open editor for blog.' - locust.get(f'/rest/watch-button/1.0/watchState/{parsed_blog_id}?_={timestamp_int()}', catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("345"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("350"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("355"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("360"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.get(f'/rest/quickreload/latest/{parsed_blog_id}?since={timestamp_int()}&_={timestamp_int()}', + # 480 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("480"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 490 plugins/macrobrowser/browse-macros.action + locust.get('/plugins/macrobrowser/browse-macros.action' + '?macroMetadataClientCacheKey=1618473279191' + '&detailed=false', catch_response=True) @@ -236,18 +411,28 @@ def search_cql_and_view_results(locust): @confluence_measure('locust_search_cql:recently_viewed') def search_recently_viewed(): - locust.get('/rest/recentlyviewed/1.0/recent?limit=8', catch_response=True) + # 520 rest/recentlyviewed/1.0/recent + locust.get('/rest/recentlyviewed/1.0/recent' + '?limit=8', + catch_response=True) @confluence_measure('locust_search_cql:search_results') def search_cql(): - r = locust.get(f"/rest/api/search?cql=siteSearch~'{generate_random_string(3, only_letters=True)}'" - f"&start=0&limit=20", catch_response=True) + # 530 rest/api/search + r = locust.get(f"/rest/api/search" + f"?cql=siteSearch~'{generate_random_string(3, only_letters=True)}'" + f"&start=0" + f"&limit=20", + catch_response=True) + if '{"results":[' not in r.content.decode('utf-8'): logger.locust_info(r.content.decode('utf-8')) content = r.content.decode('utf-8') if 'results' not in content: logger.error(f"Search cql failed: {content}") assert 'results' in content, "Search cql failed." + + # 540 rest/mywork/latest/status/notification/count locust.get('/rest/mywork/latest/status/notification/count', catch_response=True) search_recently_viewed() @@ -264,44 +449,81 @@ def open_editor_and_create_blog(locust): @confluence_measure('locust_create_blog:blog_editor') def create_blog_editor(): raise_if_login_failed(locust) - r = locust.get(f'/pages/createblogpost.action?spaceKey={blog_space_key}', catch_response=True) + + # 550 pages/createblogpost.action + r = locust.get(f'/pages/createblogpost.action' + f'?spaceKey={blog_space_key}', + catch_response=True) + content = r.content.decode('utf-8') if 'Blog post title' not in content: logger.error(f'Could not open editor for {blog_space_key}: {content}') assert 'Blog post title' in content, 'Could not open editor for blog.' - atl_token = fetch_by_re(params.atl_token_re, content) content_id = fetch_by_re(params.content_id_re, content) parsed_space_key = fetch_by_re(params.space_key, content) + parsed_page_id = fetch_by_re(params.page_id_re, content) + parent_page_id = fetch_by_re(params.parent_page_id_re, content) + + # 560 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("560"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 570 rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash} + locust.get(f'/rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash}' + f'?_={timestamp_int()}', + catch_response=True) + + # 580 rest/mywork/latest/status/notification/count + locust.get(f'/rest/mywork/latest/status/notification/count' + f'?pageId={parsed_page_id}' + f'&_={timestamp_int()}', + catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("910"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.get('/rest/mywork/latest/status/notification/count?pageId=0', catch_response=True) + # 590 rest/jiraanywhere/1.0/servers + locust.get(f'/rest/jiraanywhere/1.0/servers' + f'?_={timestamp_int()}', + catch_response=True) + + # 610 rest/mywork/latest/status/notification/count + locust.get(f'/rest/mywork/latest/status/notification/count' + f'?pageid={parsed_page_id}', + catch_response=True) + + # 620 plugins/servlet/notifications-miniview locust.get('/plugins/servlet/notifications-miniview', catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("925"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("930"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.get(f'/rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash}?_={timestamp_int()}', + + # 630 rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash} + locust.get(f'/rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash}' + f'?_={timestamp_int()}', catch_response=True) heartbeat_activity_body = {"dataType": "json", "contentId": content_id, "draftType": "blogpost", "spaceKey": parsed_space_key, - "atl_token": atl_token + "atl_token": locust.session_data_storage['token'] } - r = locust.post('/json/startheartbeatactivity.action', heartbeat_activity_body, - TEXT_HEADERS, catch_response=True) + + # 640 json/startheartbeatactivity.action + r = locust.post('/json/startheartbeatactivity.action', + heartbeat_activity_body, + TEXT_HEADERS, + catch_response=True) + content = r.content.decode('utf-8') - if atl_token not in content: - logger.error(f'Token {atl_token} not found in content: {content}') - assert atl_token in content, 'Token not found in content.' + if locust.session_data_storage['token'] not in content: + logger.error(f"Token {locust.session_data_storage['token']} not found in content: {content}") + assert locust.session_data_storage['token'] in content, 'Token not found in content.' contributor_hash = fetch_by_re(params.contribution_hash, content) locust.session_data_storage['contributor_hash'] = contributor_hash + # 650 rest/ui/1.0/content/{content_id}/labels r = locust.get(f'/rest/ui/1.0/content/{content_id}/labels', catch_response=True) + content = r.content.decode('utf-8') if '"success":true' not in content: logger.error(f'Could not get labels for content {content_id}: {content}') @@ -311,10 +533,11 @@ def create_blog_editor(): locust.session_data_storage['draft_name'] = draft_name locust.session_data_storage['parsed_space_key'] = parsed_space_key locust.session_data_storage['content_id'] = content_id - locust.session_data_storage['atl_token'] = atl_token + locust.session_data_storage['parsed_page_id'] = parsed_page_id + locust.session_data_storage['parent_page_id'] = parent_page_id draft_body = {"draftId": content_id, - "pageId": "0", + "pageId": parsed_page_id, "type": "blogpost", "title": draft_name, "spaceKey": parsed_space_key, @@ -322,7 +545,13 @@ def create_blog_editor(): "syncRev": "0.mcPCPtDvwoayMR7zvuQSbf8.27"} TEXT_HEADERS['Content-Type'] = 'application/json' - r = locust.post('/rest/tinymce/1/drafts', json=draft_body, headers=TEXT_HEADERS, catch_response=True) + + # 660 rest/tinymce/1/drafts + r = locust.post('/rest/tinymce/1/drafts', + json=draft_body, + headers=TEXT_HEADERS, + catch_response=True) + content = r.content.decode('utf-8') if 'draftId' not in content: logger.error(f'Could not create blog post draft in space {parsed_space_key}: {content}') @@ -334,7 +563,6 @@ def create_blog(): draft_name = locust.session_data_storage['draft_name'] parsed_space_key = locust.session_data_storage['parsed_space_key'] content_id = locust.session_data_storage['content_id'] - atl_token = locust.session_data_storage['atl_token'] draft_body = {"status": "current", "title": draft_name, "space": {"key": f"{parsed_space_key}"}, "body": {"editor": {"value": f"Test Performance Blog Page Content {draft_name}", @@ -342,8 +570,14 @@ def create_blog(): "id": f"{content_id}", "type": "blogpost", "version": {"number": 1, "minorEdit": True, "syncRev": "0.mcPCPtDvwoayMR7zvuQSbf8.30"}} TEXT_HEADERS['Content-Type'] = 'application/json' - r = locust.client.put(f'/rest/api/content/{content_id}?status=draft', json=draft_body, - headers=TEXT_HEADERS, catch_response=True) + + # 670 rest/api/content/{content_id}?status=draft + r = locust.client.put(f'/rest/api/content/{content_id}' + f'?status=draft', + json=draft_body, + headers=TEXT_HEADERS, + catch_response=True) + content = r.content.decode('utf-8') if 'current' not in content or 'title' not in content: logger.error(f'Could not open draft {draft_name}: {content}') @@ -351,51 +585,150 @@ def create_blog(): created_blog_title = fetch_by_re(params.created_blog_title_re, content) logger.locust_info(f'Blog {created_blog_title} created') + # 680 {created_blog_title} r = locust.get(f'/{created_blog_title}', catch_response=True) + content = r.content.decode('utf-8') if 'Created by' not in content: logger.error(f'Could not open created blog {created_blog_title}: {content}') assert 'Created by' in content, 'Could not open created blog.' - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("970"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("975"), - headers=RESOURCE_HEADERS, catch_response=True) + heartbeat_activity_body = {"dataType": "json", + "contentId": content_id, + "draftType": "blogpost", + "spaceKey": parsed_space_key, + + "atl_token": locust.session_data_storage['token'] + } + + # 690 json/stopheartbeatactivity.action + r = locust.post('/json/startheartbeatactivity.action', + heartbeat_activity_body, + TEXT_HEADERS, + catch_response=True) + + # 700 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("700"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 710 plugins/servlet/notifications-miniview locust.get('/plugins/servlet/notifications-miniview', catch_response=True) - locust.get(f'/rest/watch-button/1.0/watchState/{content_id}?_={timestamp_int()}', catch_response=True) - locust.get(f'/rest/likes/1.0/content/{content_id}/likes?commentLikes=true&_={timestamp_int()}', + + # 720 rest/watch-button/1.0/watchState/{content-id} + locust.get(f'/rest/watch-button/1.0/watchState/{content_id}' + f'?_={timestamp_int()}', + catch_response=True) + + # 730 rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("730"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 740 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("740"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 750 /rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash} + locust.get(f'/rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash}' + f'?_={timestamp_int()}', + catch_response=True) + + # 760 rest/jira-metadata/1.0/metadata/aggregate + locust.get(f'/rest/jira-metadata/1.0/metadata/aggregate' + f'?pageId={locust.session_data_storage["parsed_page_id"]}' + f'&_={timestamp_int()}', catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("995"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.get(f'/rest/highlighting/1.0/panel-items?pageId={content_id}&_={timestamp_int()}', + + # 770 rest/likes/1.0/content/{content_id}/likes + locust.get(f'/rest/likes/1.0/content/{content_id}/likes' + f'?commentLikes=true' + f'&_={timestamp_int()}', catch_response=True) - locust.get(f'/rest/inlinecomments/1.0/comments?containerId={content_id}&_={timestamp_int()}', + + # 780 rest/highlighting/1.0/panel-items + locust.get(f'/rest/highlighting/1.0/panel-items' + f'?pageId={content_id}' + f'&_={timestamp_int()}', catch_response=True) + + # 790 rest/inlinecomments/1.0/comments + locust.get(f'/rest/inlinecomments/1.0/comments' + f'?containerId={content_id}' + f'&_={timestamp_int()}', + catch_response=True) + + # 800 s/en_GB/{build-number}/{keyboardshortcut-hash}/_/images/icons/profilepics/add_profile_pic.svg locust.get(f'/s/en_GB/{build_number}/{keyboard_hash}/_/images/icons/profilepics/add_profile_pic.svg', catch_response=True) + + # 810 rest/helptips/1.0/tips locust.get('/rest/helptips/1.0/tips', catch_response=True) - locust.get(f'/rest/mywork/latest/status/notification/count?pageid={content_id}&_={timestamp_int()}', + + # 820 rest/mywork/latest/status/notification/count + locust.get(f'/rest/mywork/latest/status/notification/count' + f'?pageid={content_id}' + f'&_={timestamp_int()}', catch_response=True) - locust.get(f'/plugins/editor-loader/editor.action?parentPageId=&pageId={content_id}' - f'&spaceKey={parsed_space_key}&atl_after_login_redirect={created_blog_title}' - f'&timeout=12000&_={timestamp_int()}', catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("1030"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("1035"), - headers=RESOURCE_HEADERS, catch_response=True) - heartbeat_activity_body = {"dataType": "json", - "contentId": content_id, - "draftType": "blogpost", - "spaceKey": parsed_space_key, - "atl_token": atl_token - } - r = locust.post('/json/startheartbeatactivity.action', heartbeat_activity_body, - TEXT_HEADERS, catch_response=True) + # 830 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("830"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 840 rest/autoconvert/latest/shortcutlinkconfigurations + locust.get(f'/rest/autoconvert/latest/shortcutlinkconfigurations' + f'?_={timestamp_int()}', + catch_response=True) + + # 850 rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("850"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 880 rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("880"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 890 rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("890"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 900 plugins/editor-loader/editor.action + r = locust.get(f'/plugins/editor-loader/editor.action' + f'?parentPageId={locust.session_data_storage["parent_page_id"]}' + f'&pageId={content_id}' + f'&spaceKey={parsed_space_key}' + f'&atl_after_login_redirect=/pages/viewpage.action' + f'&timeout=12000&_={timestamp_int()}', + catch_response=True) + + # 910 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("830"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 920 json/startheartbeatactivity.action + r = locust.post('/json/startheartbeatactivity.action', + heartbeat_activity_body, + TEXT_HEADERS, + catch_response=True) + content = r.content.decode('utf-8') - if atl_token not in content: - logger.error(f'Token {atl_token} not found in content: {content}') - assert atl_token in content, 'Token not found in content.' + if locust.session_data_storage['token'] not in content: + logger.error(f"Token {locust.session_data_storage['token']} not found in content: {content}") + assert locust.session_data_storage['token'] in content, 'Token not found in content.' create_blog_editor() create_blog() @@ -412,306 +745,559 @@ def create_and_edit_page(locust): @confluence_measure('locust_create_and_edit_page:create_page_editor') def create_page_editor(): raise_if_login_failed(locust) - r = locust.get(f'/pages/createpage.action?spaceKey={space_key}&fromPageId={page_id}&src=quick-create', + + # 960 pages/createpage.action + r = locust.get(f'/pages/createpage.action' + f'?spaceKey={space_key}' + f'&fromPageId={page_id}' + f'&src=quick-create', catch_response=True) + content = r.content.decode('utf-8') if 'Page Title' not in content: logger.error(f'Could not open page editor: {content}') assert 'Page Title' in content, 'Could not open page editor.' - parsed_space_key = fetch_by_re(params.space_key_re, content) - atl_token = fetch_by_re(params.atl_token_re, content) - content_id = fetch_by_re(params.content_id_re, content) - locust.session_data_storage['content_id'] = content_id - locust.session_data_storage['atl_token'] = atl_token - - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("705"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("710"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("715"), - headers=RESOURCE_HEADERS, catch_response=True) + content_id_fetched_by_re = fetch_by_re(params.content_id_re, content) + parent_page_id_fetched_by_re = fetch_by_re(params.parent_page_id, content) + + # 970 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("970"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 980 rest/create-dialog/1.0/storage/quick-create locust.get('/rest/create-dialog/1.0/storage/quick-create', catch_response=True) - locust.get(f'/rest/mywork/latest/status/notification/count?pageid=0&_={timestamp_int()}', + + # 990 rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash} + locust.get(f'/rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash}' + f'?_={timestamp_int()}', catch_response=True) - locust.get(f'/rest/jiraanywhere/1.0/servers?_={timestamp_int()}', catch_response=True) - locust.get(f'/rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash}', catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("750"), - headers=RESOURCE_HEADERS, catch_response=True) - heartbeat_activity_body = {"dataType": "json", - "contentId": content_id, - "draftType": "page", - "spaceKey": parsed_space_key, - "atl_token": atl_token - } - r = locust.post('/json/startheartbeatactivity.action', heartbeat_activity_body, - TEXT_HEADERS, catch_response=True) - content = r.content.decode('utf-8') - if atl_token not in content: - logger.error(f'Token {atl_token} not found in content: {content}') - assert atl_token in content, 'Token not found in content.' + # 1000 plugins/macrobrowser/browse-macros.action + locust.get(f'/plugins/macrobrowser/browse-macros.action' + f'?macroMetadataClientCacheKey={timestamp_int()}' + f'&detailed=false', + catch_response=True) + + # 1010 rest/mywork/latest/status/notification/count + locust.get(f'/rest/mywork/latest/status/notification/count' + f'?pageid=0' + f'&_={timestamp_int()}', + catch_response=True) + + # 1030 rest/jiraanywhere/1.0/servers + locust.get(f'/rest/jiraanywhere/1.0/servers' + f'?_={timestamp_int()}', + catch_response=True) + + start_heartbeat_activity_body = {"dataType": "json", + "contentId": content_id_fetched_by_re, + "draftType": "page", + "spaceKey": space_key, + "atl_token": locust.session_data_storage['token'] + } + + # 1040 json/startheartbeatactivity.action + r = locust.post('/json/startheartbeatactivity.action', + start_heartbeat_activity_body, + TEXT_HEADERS, + catch_response=True) + + contributor_hash = r.json().get("contributorsHash", None) + if contributor_hash is None: + logger.error(f'The "contributorsHash" key was not found in content: {r.json()}') + assert contributor_hash is not None, 'The "contributorsHash" key was not found in content.' + + # 1050 rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash} + locust.get(f'/rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash}' + f'?_={timestamp_int()}', + catch_response=True) + + # 1080 rest/autoconvert/latest/shortcutlinkconfigurations + locust.get(f'/rest/autoconvert/latest/shortcutlinkconfigurations' + f'?_={timestamp_int()}', + catch_response=True) + + # 1090 rest/ui/1.0/content/{content_id}/labels + locust.get(f'/rest/ui/1.0/content/{content_id_fetched_by_re}/labels' + f'?_={timestamp_int()}', + catch_response=True) + + # 1100 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("1100"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1110 rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("1110"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1120 rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("1120"), + headers=RESOURCE_HEADERS, + catch_response=True) + + locust.session_data_storage["content_id"] = content_id_fetched_by_re + locust.session_data_storage["parent_page_id"] = parent_page_id_fetched_by_re + locust.session_data_storage["contributor_hash"] = contributor_hash @confluence_measure('locust_create_and_edit_page:create_page') def create_page(): raise_if_login_failed(locust) draft_name = f"{generate_random_string(10, only_letters=True)}" - content_id = locust.session_data_storage['content_id'] - atl_token = locust.session_data_storage['atl_token'] - create_page_body = { - "status": "current", - "title": f"Test Performance JMeter {draft_name}", - "space": {"key": f"{space_key}"}, - "body": { - "storage": { - "value": f"Test Performance Create Page Content {draft_name}", - "representation": "storage", - "content": { - "id": f"{content_id}" - } - } - }, - "id": f"{content_id}", - "type": "page", - "version": { - "number": 1 - }, - "ancestors": [ - { - "id": f"{page_id}", - "type": "page" - } - ] - } + title = f"locust_create_and_edit_page:create_page - {draft_name}" + body_editor_value = f"Test Performance Create Page Content {draft_name}" + + create_page_body_data = {"status": "current", + "title": title, + "space": { + "key": space_key + }, + "body": { + "editor": { + "value": body_editor_value, + "representation": "editor", + "content": { + "id": locust.session_data_storage['content_id'] + } + } + }, + "id": locust.session_data_storage['content_id'], + "type": "page", + "version": { + "number": 1, + "minorEdit": "true", + "syncRev": "0.RIi4Ras2AToROk0WlzfpzBg.2" + }, + "ancestors": [ + { + "id": locust.session_data_storage['parent_page_id'], + "type": "page" + } + ] + } TEXT_HEADERS['Content-Type'] = 'application/json' TEXT_HEADERS['X-Requested-With'] = 'XMLHttpRequest' - r = locust.client.put(f'/rest/api/content/{content_id}?status=draft', json=create_page_body, - headers=TEXT_HEADERS, catch_response=True) - content = r.content.decode('utf-8') - if 'draftId' not in content: + + start_heartbeat_activity_body = {"dataType": "json", + "contentId": locust.session_data_storage["content_id"], + "space_key": space_key, + "draftType": "page", + "atl_token": locust.session_data_storage['token'], + "contributorsHash": locust.session_data_storage['contributor_hash'], + } + + stop_heartbeat_activity_body = {"dataType": "json", + "contentId": locust.session_data_storage["content_id"], + "draftType": "page", + "atl_token": locust.session_data_storage['token'], + } + + # 1130 json/startheartbeatactivity.action + locust.post('/json/startheartbeatactivity.action', + params=start_heartbeat_activity_body, + headers=TEXT_HEADERS, + catch_response=True) + + # 1140 rest/api/content/content_id?status=draft + r = locust.client.put(f'/rest/api/content/{locust.session_data_storage["content_id"]}' + f'?status=draft', + json=create_page_body_data, + headers=TEXT_HEADERS, + catch_response=True) + + content = r.json() + page_title = content.get('title', None) + + if page_title is None: logger.error(f'Could not create PAGE draft: {content}') - assert 'draftId' in content, 'Could not create PAGE draft.' - page_title = fetch_by_re(params.page_title_re, content) + assert page_title is not None, 'Could not create PAGE draft.' - r = locust.get(f'{page_title}', catch_response=True) - content = r.content.decode('utf-8') - if 'Created by' not in content: - logger.error(f'Page {page_title} was not created: {content}') - assert 'Created by' in content, 'Page was not created.' + locust.session_data_storage['draft_name'] = draft_name - parent_page_id = fetch_by_re(params.parent_page_id, content) - create_page_id = fetch_by_re(params.create_page_id, content) - locust.session_data_storage['create_page_id'] = create_page_id - locust.session_data_storage['parent_page_id'] = parent_page_id + # 1045 rest/mywork/latest/status/notification/count + locust.get(f'/rest/mywork/latest/status/notification/count' + f'?_{timestamp_int()}', + catch_response=True) - heartbeat_activity_body = {"dataType": "json", - "contentId": content_id, - "space_key": space_key, - "draftType": "page", - "atl_token": atl_token - } - locust.post('/json/stopheartbeatactivity.action', params=heartbeat_activity_body, - headers=TEXT_HEADERS, catch_response=True) + # 1150 json/stopheartbeatactivity.action + locust.post('/json/stopheartbeatactivity.action', + params=stop_heartbeat_activity_body, + headers=TEXT_HEADERS, + catch_response=True) + + # 1160 display/{space_key}/{page_title} + locust.get(f'/display/{space_key}/{page_title}', catch_response=True) + + # 1170 json/startheartbeatactivity.action + locust.post('/json/startheartbeatactivity.action', + params=start_heartbeat_activity_body, + headers=TEXT_HEADERS, + catch_response=True) + # 1180 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("1180"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1190 rest/helptips/1.0/tips locust.get('/rest/helptips/1.0/tips', catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("795"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.get(f'/rest/jira-metadata/1.0/metadata/aggregate?pageId={create_page_id}&_={timestamp_int()}', + + # 1200 rest/inlinecomments/1.0/comments + locust.get(f'/rest/inlinecomments/1.0/comments' + f'?containerId={locust.session_data_storage["content_id"]}' + f'&_={timestamp_int()}', + catch_response=True) + + # 1210 rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash} + locust.get(f'/rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash}' + f'?_={timestamp_int()}', catch_response=True) - locust.get(f'/rest/likes/1.0/content/{create_page_id}/likes?commentLikes=true&_={timestamp_int()}', + + # 1220 plugins/pagetree/naturalchildren.action + locust.get(f'/plugins/pagetree/naturalchildren.action' + f'?decorator=none' + f'&expandCurrent=true' + f'&mobile=false' + f'&sort=position' + f'&reverse=false' + f'&spaceKey={space_key}' + f'&treeId=0' + f'&hasRoot=false' + f'&startDepth=0' + f'&disableLinks=false' + f'&placement=sidebar' + f'&excerpt=false' + f'&ancestors={locust.session_data_storage["parent_page_id"]}' + f'&treePageId=0' + f'&_={timestamp_int()}', catch_response=True) - locust.get(f'/rest/inlinecomments/1.0/comments?containerId={create_page_id}&_={timestamp_int()}', + + # 1230 rest/jira-metadata/1.0/metadata/aggregate + locust.get(f'/rest/jira-metadata/1.0/metadata/aggregate' + f'?pageId=0' + f'&_={timestamp_int()}', catch_response=True) - locust.get(f'/rest/mywork/latest/status/notification/count?pageid={create_page_id}&_={timestamp_int()}', + + # 1240 rest/likes/1.0/content/{content_id}/likes + locust.get(f'/rest/likes/1.0/content/{locust.session_data_storage["content_id"]}/likes' + f'?commentLikes=true' + f'&_={timestamp_int()}', catch_response=True) - locust.get(f'/rest/highlighting/1.0/panel-items?pageId={create_page_id}&_={timestamp_int()}', + + # 1250 rest/highlighting/1.0/panel-items + locust.get(f'/rest/highlighting/1.0/panel-items' + f'?pageId=0' + f'&_={timestamp_int()}', catch_response=True) - locust.get(f'/rest/watch-button/1.0/watchState/{create_page_id}?_={timestamp_int()}', + + # 1260 rest/mywork/latest/status/notification/count + locust.get(f'/rest/mywork/latest/status/notification/count' + f'?pageid=0' + f'&_={timestamp_int()}', catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("830"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("835"), - headers=RESOURCE_HEADERS, catch_response=True) - r = locust.get(f'/plugins/editor-loader/editor.action?parentPageId={parent_page_id}' - f'&pageId={create_page_id}&spaceKey={space_key}' - f'&atl_after_login_redirect={page_title}&timeout=12000&_={timestamp_int()}', + # 1270 rest/watch-button/1.0/watchState/{content_id} + locust.get(f'/rest/watch-button/1.0/watchState/{locust.session_data_storage["content_id"]}' + f'?_={timestamp_int()}', + catch_response=True) + + # 1280 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("1280"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1290 plugins/editor-loader/editor.action + r = locust.get(f'/plugins/editor-loader/editor.action' + f'?parentPageId={locust.session_data_storage["parent_page_id"]}' + f'&pageId={locust.session_data_storage["content_id"]}' + f'&spaceKey={space_key}' + f'&atl_after_login_redirect=/display/{space_key}/{page_title}' + f'&timeout=12000&_={timestamp_int()}', catch_response=True) + content = r.content.decode('utf-8') if page_title not in content: - logger.error(f'Page editor load failed for page {page_title}: {content}') + logger.error(f'{page_title}: {content}') assert page_title in content, 'Page editor load failed for page.' - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("845"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("850"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("855"), - headers=RESOURCE_HEADERS, catch_response=True) + # 1300 rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("1300"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1310 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("1310"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1320 plugins/macrobrowser/browse-macros.action + locust.get('/plugins/macrobrowser/browse-macros.action' + '?macroMetadataClientCacheKey=1618492783694' + '&detailed=false', + catch_response=True) @confluence_measure('locust_create_and_edit_page:open_editor') def open_editor(): raise_if_login_failed(locust) - create_page_id = locust.session_data_storage['create_page_id'] + start_heartbeat_activity_body = {"dataType": "json", + "contentId": locust.session_data_storage["content_id"], + "space_key": space_key, + "draftType": "page", + "atl_token": locust.session_data_storage['token'], + } + + # 1360 rest/tinymce/1/content/{content_id}.json + locust.get(f'/rest/tinymce/1/content/{locust.session_data_storage["content_id"]}.json' + f'?_={timestamp_int()}', + catch_response=True) - r = locust.get(f'/pages/editpage.action?pageId={create_page_id}', catch_response=True) - content = r.content.decode('utf-8') - if 'Edit' not in content or 'Update</button>' not in content: - logger.error(f'Could not open PAGE {create_page_id} to edit: {content}') - assert '<title>Edit' in content and 'Update</button>' in content, \ - 'Could not open PAGE to edit.' - - edit_page_version = fetch_by_re(params.editor_page_version_re, content) - edit_atl_token = fetch_by_re(params.atl_token_re, content) - edit_space_key = fetch_by_re(params.space_key_re, content) - edit_content_id = fetch_by_re(params.content_id_re, content) - edit_page_id = fetch_by_re(params.page_id_re, content) - edit_parent_page_id = fetch_by_re(params.parent_page_id, content) - - locust.session_data_storage['edit_parent_page_id'] = edit_parent_page_id - locust.session_data_storage['edit_page_version'] = edit_page_version - locust.session_data_storage['edit_page_id'] = edit_page_id - locust.session_data_storage['atl_token'] = edit_atl_token - locust.session_data_storage['edit_content_id'] = edit_content_id - - locust.get(f'/rest/jiraanywhere/1.0/servers?_={timestamp_int()}', catch_response=True) - heartbeat_activity_body = {"dataType": "json", - "contentId": edit_content_id, - "draftType": "page", - "spaceKey": edit_space_key, - "atl_token": edit_atl_token - } - locust.post('/json/startheartbeatactivity.action', heartbeat_activity_body, - TEXT_HEADERS, catch_response=True) - expand = 'history.createdBy.status%2Chistory.contributors.publishers.users.status' \ - '%2Cchildren.comment.version.by.status' - locust.get(f'/rest/api/content/{edit_page_id}?expand={expand}&_={timestamp_int()}', - catch_response=True) - locust.post('/json/startheartbeatactivity.action', heartbeat_activity_body, - TEXT_HEADERS, catch_response=True) - locust.get(f'/rest/ui/1.0/content/{edit_page_id}/labels?_={timestamp_int()}', catch_response=True) - locust.get('/rest/mywork/latest/status/notification/count', catch_response=True) - locust.post('/json/startheartbeatactivity.action', heartbeat_activity_body, - TEXT_HEADERS, catch_response=True) + # 1370 rest/jiraanywhere/1.0/servers + locust.get(f'/rest/jiraanywhere/1.0/servers' + f'?_={timestamp_int()}', + catch_response=True) + + # 1380 rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash} + locust.get(f'/rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash}' + f'?_={timestamp_int()}', + catch_response=True) + + # 1390 json/startheartbeatactivity.action + locust.post('/json/startheartbeatactivity.action', + params=start_heartbeat_activity_body, + headers=TEXT_HEADERS, + catch_response=True) + + # 1400 rest/api/content/{content_id} + locust.get(f'/rest/api/content/{locust.session_data_storage["content_id"]}' + f'?expand=history.createdBy.status,history.contributors.publishers.users.status,' + f'children.comment.version.by.status' + f'&_={timestamp_int()}', + catch_response=True) + + # 1410 rest/autoconvert/latest/shortcutlinkconfigurations + locust.get(f'/rest/autoconvert/latest/shortcutlinkconfigurations' + f'?_={timestamp_int()}', + catch_response=True) + + # 1420 rest/autoconvert/latest/shortcutlinkconfigurations + locust.get(f'/rest/ui/1.0/content/{locust.session_data_storage["content_id"]}/labels' + f'?_={timestamp_int()}', + catch_response=True) + + # 1430 rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("1430"), + headers=TEXT_HEADERS, + catch_response=True) + + # 1440 rest/mywork/latest/status/notification/count + locust.get(f'/rest/mywork/latest/status/notification/count' + f'?_={timestamp_int()}', + catch_response=True) + + # 1450 rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("1450"), + headers=TEXT_HEADERS, + catch_response=True) @confluence_measure('locust_create_and_edit_page:edit_page') def edit_page(): raise_if_login_failed(locust) locust.session_data_storage['draft_name'] = f"{generate_random_string(10, only_letters=True)}" - edit_parent_page_id = locust.session_data_storage['edit_parent_page_id'] - edit_page_id = locust.session_data_storage['edit_page_id'] - content_id = locust.session_data_storage['edit_content_id'] - edit_page_version = int(locust.session_data_storage['edit_page_version']) + 1 - edit_atl_token = locust.session_data_storage['atl_token'] - edit_page_body = dict() - - if edit_parent_page_id: - edit_page_body = { - "status": "current", - "title": f"Test Performance Edit with locust {locust.session_data_storage['draft_name']}", - "space": { - "key": f"{space_key}" - }, - "body": { - "storage": { - "value": f"Page edit with locust {locust.session_data_storage['draft_name']}", - "representation": "storage", - "content": { - "id": f"{content_id}" - } - } - }, - "id": f"{content_id}", - "type": "page", - "version": { - "number": f"{edit_page_version}" - }, - "ancestors": [ - { - "id": f"{edit_parent_page_id}", - "type": "page" - } - ] - } - - if not edit_parent_page_id: - edit_page_body = { - "status": "current", - "title": f"Test Performance Edit with locust {locust.session_data_storage['draft_name']}", + title = f"locust_create_and_edit_page:edit_page - {locust.session_data_storage['draft_name']}" + body_editor_value = f"<p>Page edit with locust {locust.session_data_storage['draft_name']}</p>" + + TEXT_HEADERS['Content-Type'] = 'application/json' + TEXT_HEADERS['X-Requested-With'] = 'XMLHttpRequest' + + start_heartbeat_activity_body = {"dataType": "json", + "contentId": locust.session_data_storage["content_id"], + "space_key": space_key, + "draftType": "page", + "atl_token": locust.session_data_storage['token'], + "contributorsHash": locust.session_data_storage['contributor_hash'], + } + + stop_heartbeat_activity_body = {"dataType": "json", + "contentId": locust.session_data_storage["content_id"], + "draftType": "page", + "atl_token": locust.session_data_storage['token'], + } + + edt_page_body_data = {"status": "current", + "title": title, "space": { - "key": f"{space_key}" + "key": space_key }, "body": { - "storage": { - "value": f"Page edit with locust {locust.session_data_storage['draft_name']}", - "representation": "storage", - "content": { - "id": f"{content_id}" + "editor": { + "value": body_editor_value, + "representation": "editor", + "content": { + "id": locust.session_data_storage['content_id'] + } } - } }, - "id": f"{content_id}", + "id": locust.session_data_storage['content_id'], "type": "page", "version": { - "number": f"{edit_page_version}" + "number": 2, + "message": "", + "minorEdit": "false", + "syncRev": "0.oLWs6S5l3gY2mwHJiA9jHao.5" + }, + "ancestors": [ + { + "id": locust.session_data_storage['parent_page_id'], + "type": "page" + } + ] } - } - TEXT_HEADERS['Content-Type'] = 'application/json' - TEXT_HEADERS['X-Requested-With'] = 'XMLHttpRequest' - r = locust.client.put(f'/rest/api/content/{content_id}?status=draft', json=edit_page_body, - headers=TEXT_HEADERS, catch_response=True) - content = r.content.decode('utf-8') - if 'history' not in content: + # 1460 json/startheartbeatactivity.action + locust.post('/json/startheartbeatactivity.action', + params=start_heartbeat_activity_body, + headers=TEXT_HEADERS, + catch_response=True) + + # 1470 rest/api/content/{content_id}?status=draft + r = locust.client.put(f'/rest/api/content/{locust.session_data_storage["content_id"]}' + f'?status=draft', + json=edt_page_body_data, + headers=TEXT_HEADERS, + catch_response=True) + + content = r.json() + page_title = content.get('title', None) + + if page_title is None: logger.info(f'Could not edit page. Response content: {content}') - if 'history' not in content: - logger.error(f'User {locust.session_data_storage["username"]} could not edit page {content_id}, ' - f'parent page id: {edit_parent_page_id}: {content}') - assert 'history' in content, \ - 'User could not edit page.' + logger.error(f'User {locust.session_data_storage["username"]} could not edit page ' + f'{locust.session_data_storage["content_id"]}, ' + f'parent page id: {locust.session_data_storage["parent_page_id"]}: {content}') + assert page_title is not None, 'User could not edit page.' + + # 1480 json/stopheartbeatactivity.action + locust.post('/json/stopheartbeatactivity.action', + params=stop_heartbeat_activity_body, + headers=TEXT_HEADERS, + catch_response=True) - r = locust.get(f'/pages/viewpage.action?pageId={edit_page_id}', catch_response=True) - content = r.content.decode('utf-8') - if not('last-modified' in content and 'Created by' in content): - logger.error(f"Could not open page {edit_page_id}: {content}") - assert 'last-modified' in content and 'Created by' in content, "Could not open page to edit." + # 1490 /display/${space_key}/${page_title} + locust.get(f'/display/{space_key}/{page_title}', + catch_response=True) - locust.get('/rest/mywork/latest/status/notification/count', catch_response=True) - heartbeat_activity_body = {"dataType": "json", - "contentId": content_id, - "space_key": space_key, - "draftType": "page", - "atl_token": edit_atl_token - } - locust.post('/json/stopheartbeatactivity.action', params=heartbeat_activity_body, - headers=TEXT_HEADERS, catch_response=True) + # 1500 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("1500"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1510 rest/helptips/1.0/tips locust.get('/rest/helptips/1.0/tips', catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("1175"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.get(f'/rest/jira-metadata/1.0/metadata/aggregate?pageId={edit_page_id}&_={timestamp_int()}', + + locust.get(f'/rest/inlinecomments/1.0/comments' + f'?containerId={locust.session_data_storage["content_id"]}' + f'&_={timestamp_int()}', catch_response=True) - locust.get(f'/rest/likes/1.0/content/{edit_page_id}/likes?commentLikes=true&_={timestamp_int()}', + + # 1530 rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash} + locust.get(f'/rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash}' + f'?_={timestamp_int()}', catch_response=True) - locust.get(f'/rest/highlighting/1.0/panel-items?pageId={edit_page_id}&_={timestamp_int()}', + + # 1540 plugins/pagetree/naturalchildren.action + locust.get(f'/plugins/pagetree/naturalchildren.action' + f'?decorator=none' + f'&expandCurrent=true' + f'&mobile=false' + f'&sort=position' + f'&reverse=false' + f'&spaceKey={space_key}' + f'&treeId=0' + f'&hasRoot=false' + f'&startDepth=0' + f'&disableLinks=false' + f'&placement=sidebar' + f'&excerpt=false' + f'&ancestors={locust.session_data_storage["parent_page_id"]}' + f'&treePageId={space_key}' + f'&_={timestamp_int()}', + catch_response=True) + + # 1550 rest/jira-metadata/1.0/metadata/aggregate + locust.get(f'/rest/jira-metadata/1.0/metadata/aggregate' + f'?pageId={page_id}' + f'&_={timestamp_int()}', + catch_response=True) + + # 1560 rest/likes/1.0/content/{content_id}/likes + locust.get(f'/rest/likes/1.0/content/{locust.session_data_storage["content_id"]}/likes' + f'?commentLikes=true' + f'&_={timestamp_int()}', catch_response=True) - locust.get(f'/rest/mywork/latest/status/notification/count?pageId={edit_page_id}&_={timestamp_int()}', + + # 1570 rest/highlighting/1.0/panel-items + locust.get(f'/rest/highlighting/1.0/panel-items' + f'?pageId={page_id}' + f'&_={timestamp_int()}', catch_response=True) - locust.get(f'/plugins/editor-loader/editor.action?parentPageId={edit_parent_page_id}' - f'&pageId={edit_page_id}&spaceKey={space_key}&atl_after_login_redirect=/pages/viewpage.action' - f'&timeout=12000&_={timestamp_int()}', catch_response=True) - locust.get(f'/rest/inlinecomments/1.0/comments?containerId={content_id}&_={timestamp_int()}', + + # 1580 rest/mywork/latest/status/notification/count + locust.get(f'/rest/mywork/latest/status/notification/count' + f'?pageid={page_id}' + f'&_={timestamp_int()}', catch_response=True) + + # 1590 rest/watch-button/1.0/watchState/{content_id} + locust.get(f'/rest/watch-button/1.0/watchState/{locust.session_data_storage["content_id"]}' + f'?_={timestamp_int()}', catch_response=True) - locust.get(f'/rest/watch-button/1.0/watchState/{edit_page_id}?_={timestamp_int()}', + + # 1600 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("1600"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1610 plugins/editor-loader/editor.action + locust.get(f'/plugins/editor-loader/editor.action?parent' + f'parentPageId={locust.session_data_storage["parent_page_id"]}' + f'&pageId={locust.session_data_storage["content_id"]}' + f'&spaceKey={space_key}' + f'&atl_after_login_redirect=/pages/viewpage.action' + f'&timeout=12000' + f'&_={timestamp_int()}', catch_response=True) + + # 1620 rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("1620"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1630 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("1630"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1640 plugins/macrobrowser/browse-macros.action + locust.get('/plugins/macrobrowser/browse-macros.action' + '?macroMetadataClientCacheKey=1618492783694' + '&detailed=false', catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("1215"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("1220"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("1225"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("1230"), - headers=RESOURCE_HEADERS, catch_response=True) create_page_editor() create_page() @@ -721,31 +1307,166 @@ def edit_page(): @confluence_measure('locust_comment_page') def comment_page(locust): - raise_if_login_failed(locust) + params = CommentPage() page = random.choice(confluence_dataset["pages"]) page_id = page[0] - comment = f'<p>{generate_random_string(length=15, only_letters=True)}</p>' + space_key = page[1] + comment_text = generate_random_string(length=15, only_letters=True) + comment = f'<div style="display: none;"><br /></div><p>{comment_text}</p>' uid = str(uuid.uuid4()) - r = locust.post(f'/rest/tinymce/1/content/{page_id}/comment?actions=true', - params={'html': comment, 'watch': True, 'uuid': uid}, headers=NO_TOKEN_HEADERS, + build_number = locust.session_data_storage.get('build_number', '') + keyboard_hash = locust.session_data_storage.get('keyboard_hash', '') + + start_heartbeat_activity_body = {"dataType": "json", + "contentId": page_id, + "space_key": space_key, + "draftType": "comment", + "atl_token": locust.session_data_storage['token'], + } + + # 1680 rest/jiraanywhere/1.0/servers + locust.get(f'/rest/jiraanywhere/1.0/servers' + f'?_={timestamp_int()}', + catch_response=True) + + # 1690 /rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash} + locust.get(f'/rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash}' + f'?_={timestamp_int()}', + catch_response=True) + + # 1700 json/startheartbeatactivity.action + locust.post('/json/startheartbeatactivity.action', + params=start_heartbeat_activity_body, + headers=TEXT_HEADERS, + catch_response=True) + + # 1710 rest/autoconvert/latest/shortcutlinkconfigurations + locust.get(f'/rest/autoconvert/latest/shortcutlinkconfigurations' + f'?_={timestamp_int()}', + catch_response=True) + + # 1720 rest/mywork/latest/status/notification/count + locust.get(f'/rest/mywork/latest/status/notification/count' + f'?_={timestamp_int()}', + catch_response=True) + + # 1730 rest/tinymce/1/content/{page_id}/comment + r = locust.post(f'/rest/tinymce/1/content/{page_id}/comment' + f'?actions=true', + params={'html': comment, 'watch': True, 'uuid': uid}, + headers=NO_TOKEN_HEADERS, catch_response=True) + content = r.content.decode('utf-8') - if not('reply-comment' in content and 'edit-comment' in content): + if comment_text not in content: logger.error(f'Could not add comment: {content}') - assert 'reply-comment' in content and 'edit-comment' in content, 'Could not add comment.' + assert comment_text in content, 'Could not add comment.' + + # 1740 rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("1740"), + headers=RESOURCE_HEADERS, + catch_response=True) @confluence_measure('locust_view_attachment') def view_attachments(locust): raise_if_login_failed(locust) + + params = ViewAttachment() page = random.choice(confluence_dataset["pages"]) page_id = page[0] - r = locust.get(f'/pages/viewpageattachments.action?pageId={page_id}', catch_response=True) + space_key = page[1] + + # 1750 rest/quickreload/latest/{page_id} + locust.get(f'/rest/quickreload/latest/{page_id}' + f'?since={timestamp_int()}' + f'&_={timestamp_int()}', + catch_response=True) + + # 1760 pages/viewpageattachments.action + r = locust.get(f'/pages/viewpageattachments.action' + f'?pageId={page_id}', + catch_response=True) + content = r.content.decode('utf-8') - if not('Upload file' in content and 'Attach more files' in content or 'currently no attachments' in content): + + if not ('Upload file' in content and 'Attach more files' in content or 'currently no attachments' in content): logger.error(f'View attachments failed: {content}') assert 'Upload file' in content and 'Attach more files' in content \ or 'currently no attachments' in content, 'View attachments failed.' + build_number = fetch_by_re(params.build_number_re, content) + keyboard_hash = fetch_by_re(params.keyboard_hash_re, content) + parent_page_id = fetch_by_re(params.parent_page_id_re, content) + + # 1770 rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash} + locust.get(f'/rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash}' + f'?_={timestamp_int()}', + catch_response=True) + + # 1790 rest/mywork/latest/status/notification/count + locust.get(f'/rest/mywork/latest/status/notification/count' + f'?pageid={page_id}' + f'&_={timestamp_int()}', catch_response=True) + + # 1800 plugins/pagetree/naturalchildren.action + locust.get(f'/plugins/pagetree/naturalchildren.action' + f'?decorator=none' + f'&expandCurrent=true' + f'&mobile=false' + f'&sort=position' + f'&reverse=false' + f'&spaceKey={space_key}' + f'&treeId=0' + f'&hasRoot=false' + f'&startDepth=0' + f'&disableLinks=false' + f'&placement=sidebar' + f'&excerpt=false' + f'&ancestors={parent_page_id}' + f'&treePageId={page_id}' + f'&_={timestamp_int()}', + catch_response=True) + + # 1810 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("1810"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1820 plugins/editor-loader/editor.action + locust.get(f'/plugins/editor-loader/editor.action?parent' + f'parentPageId={parent_page_id}' + f'&pageId={page_id}' + f'&spaceKey={space_key}' + f'&atl_after_login_redirect=/pages/viewpage.action' + f'&timeout=12000' + f'&_={timestamp_int()}', + catch_response=True) + + # 1830 rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("1830"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1840 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("1840"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1850 plugins/macrobrowser/browse-macros.action + locust.get('/plugins/macrobrowser/browse-macros.action' + '?macroMetadataClientCacheKey=1618579820365' + '&detailed=false', + catch_response=True) + + # 1890 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("1890"), + headers=RESOURCE_HEADERS, + catch_response=True) @confluence_measure('locust_upload_attachment') @@ -758,27 +1479,103 @@ def upload_attachments(locust): file_name = static_content[2] file_extension = static_content[1] page_id = page[0] + space_key = page[1] r = locust.get(f'/pages/viewpage.action?pageId={page_id}', catch_response=True) content = r.content.decode('utf-8') if not('Created by' in content and 'Save for later' in content): logger.error(f'Failed to open page {page_id}: {content}') assert 'Created by' in content and 'Save for later' in content, 'Failed to open page to upload attachments.' - atl_token_view_issue = fetch_by_re(params.atl_token_view_issue_re, content) + build_number = fetch_by_re(params.build_number_re, content) + keyboard_hash = fetch_by_re(params.keyboard_hash_re, content) + parent_page_id = fetch_by_re(params.parent_page_id_re, content) multipart_form_data = { "file": (file_name, open(file_path, 'rb'), file_extension) } - r = locust.post(f'/pages/doattachfile.action?pageId={page_id}', - params={"atl_token": atl_token_view_issue, "comment_0": "", "comment_1": "", "comment_2": "", - "comment_3": "", "comment_4": "0", "confirm": "Attach"}, files=multipart_form_data, + # 1900 pages/doattachfile.action?pageId={page_id} + r = locust.post(f'/pages/doattachfile.action' + f'?pageId={page_id}', + params={"atl_token": locust.session_data_storage['token'], "comment_0": "", "comment_1": "", + "comment_2": "", "comment_3": "", "comment_4": "0", "confirm": "Attach"}, + files=multipart_form_data, catch_response=True) content = r.content.decode('utf-8') if not('Upload file' in content and 'Attach more files' in content): logger.error(f'Could not upload attachments: {content}') assert 'Upload file' in content and 'Attach more files' in content, 'Could not upload attachments.' + # 1910 rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash} + locust.get(f'/rest/shortcuts/latest/shortcuts/{build_number}/{keyboard_hash}' + f'?_={timestamp_int()}', + catch_response=True) + + # 1920 plugins/pagetree/naturalchildren.action + locust.get(f'/plugins/pagetree/naturalchildren.action' + f'?decorator=none' + f'&expandCurrent=true' + f'&mobile=false' + f'&sort=position' + f'&reverse=false' + f'&spaceKey={space_key}' + f'&treeId=0' + f'&hasRoot=false' + f'&startDepth=0' + f'&disableLinks=false' + f'&placement=sidebar' + f'&excerpt=false' + f'&ancestors={parent_page_id}' + f'&treePageId={page_id}' + f'&_={timestamp_int()}', + catch_response=True) + + # 1930 rest/mywork/latest/status/notification/count + locust.get(f'/rest/mywork/latest/status/notification/count' + f'?pageid={page_id}' + f'&_={timestamp_int()}', + catch_response=True) + + # 1940 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("1940"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1950 rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("1950"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1960 plugins/editor-loader/editor.action + locust.get(f'/plugins/editor-loader/editor.action?parent' + f'parentPageId={parent_page_id}' + f'&pageId={page_id}' + f'&spaceKey={space_key}' + f'&atl_after_login_redirect=/pages/viewpage.action' + f'&timeout=12000' + f'&_={timestamp_int()}', + catch_response=True) + + # 1970 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("1970"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1980 plugins/macrobrowser/browse-macros.action + locust.get('/plugins/macrobrowser/browse-macros.action' + '?macroMetadataClientCacheKey=1618624163503' + '&detailed=false', + catch_response=True) + + # 1990 rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("1990"), + headers=RESOURCE_HEADERS, + catch_response=True) + @confluence_measure('locust_like_page') def like_page(locust): @@ -788,14 +1585,24 @@ def like_page(locust): page_id = page[0] JSON_HEADERS['Origin'] = CONFLUENCE_SETTINGS.server_url - r = locust.get(f'/rest/likes/1.0/content/{page_id}/likes', headers=JSON_HEADERS, catch_response=True) + + # 2030 rest/likes/1.0/content/{page_id}/likes + r = locust.get(f'/rest/likes/1.0/content/{page_id}/likes', + headers=JSON_HEADERS, + catch_response=True) + content = r.content.decode('utf-8') like = fetch_by_re(params.like_re, content) if like is None: - r = locust.post(f'/rest/likes/1.0/content/{page_id}/likes', headers=JSON_HEADERS, catch_response=True) + # 2050 rest/likes/1.0/content/{page_id}/likes + r = locust.post(f'/rest/likes/1.0/content/{page_id}/likes', + headers=JSON_HEADERS, + catch_response=True) else: - r = locust.client.delete(f'/rest/likes/1.0/content/{page_id}/likes', catch_response=True) + # 2040 rest/likes/1.0/content/${page_id}/likes + r = locust.client.delete(f'/rest/likes/1.0/content/{page_id}/likes', + catch_response=True) content = r.content.decode('utf-8') if 'likes' not in content: diff --git a/app/locustio/confluence/locustfile.py b/app/locustio/confluence/locustfile.py index 1d8038c16..9e9a5ab8e 100644 --- a/app/locustio/confluence/locustfile.py +++ b/app/locustio/confluence/locustfile.py @@ -2,9 +2,9 @@ from extension.confluence.extension_locust import app_specific_action from locustio.common_utils import LocustConfig, MyBaseTaskSet -from locustio.confluence.http_actions import login_and_view_dashboard, view_page_and_tree, view_dashboard, view_blog, \ +from locustio.confluence.http_actions import login_and_view_dashboard, view_dashboard, view_blog, \ search_cql_and_view_results, open_editor_and_create_blog, create_and_edit_page, comment_page, view_attachments, \ - upload_attachments, like_page + upload_attachments, like_page, view_page from util.conf import CONFLUENCE_SETTINGS config = LocustConfig(config_yml=CONFLUENCE_SETTINGS) @@ -18,7 +18,7 @@ def on_start(self): @task(config.percentage('view_page')) def view_page_action(self): - view_page_and_tree(self) + view_page(self) @task(config.percentage('view_dashboard')) def view_dashboard_action(self): diff --git a/app/locustio/confluence/requests_params.py b/app/locustio/confluence/requests_params.py index e2ef9b219..882a538f0 100644 --- a/app/locustio/confluence/requests_params.py +++ b/app/locustio/confluence/requests_params.py @@ -33,6 +33,7 @@ class Login(ConfluenceResource): static_resource_url_re = 'meta name=\"ajs-static-resource-url-prefix\" content=\"(.*?)/_\">' version_number_re = 'meta name=\"ajs-version-number\" content=\"(.*?)\">' build_number_re = 'meta name=\"ajs-build-number\" content=\"(.*?)\"' + atl_token_pattern = r'"ajs-atl-token" content="(.+?)"' class ViewPage(ConfluenceResource): @@ -44,7 +45,6 @@ class ViewPage(ConfluenceResource): tree_result_id_re = 'name="treeRequestId" value="(.+?)"' has_no_root_re = '"noRoot" value="(.+?)"' root_page_id_re = 'name="rootPageId" value="(.+?)"' - atl_token_view_issue_re = '"ajs-atl-token" content="(.+?)"' editable_re = 'id=\"editPageLink\" href="(.+?)\?pageId=(.+?)\"' inline_comment_re = '\"id\":(.+?)\,\"' @@ -62,16 +62,18 @@ class ViewBlog(ConfluenceResource): parent_page_id_re = 'meta name=\"ajs-parent-page-id\" content=\"(.*?)\"' page_id_re = 'meta name=\"ajs-page-id\" content=\"(.*?)\">' space_key_re = 'meta id=\"confluence-space-key\" name=\"confluence-space-key\" content=\"(.*?)\"' - atl_token_re = '"ajs-atl-token" content="(.+?)"' inline_comment_re = '\"id\":(.+?)\,\"' + keyboard_hash_re = 'name=\"ajs-keyboardshortcut-hash\" content=\"(.*?)\">' + build_number_re = 'meta name=\"ajs-build-number\" content=\"(.*?)\"' class CreateBlog(ConfluenceResource): action_name = 'create_blog' - atl_token_re = 'name=\"ajs-atl-token\" content=\"(.*?)\">' content_id_re = 'name=\"ajs-content-id\" content=\"(.*?)\">' + page_id_re = 'meta name=\"ajs-page-id\" content=\"(.*?)\">' space_key = 'createpage.action\?spaceKey=(.+?)\&' contribution_hash = '\"contributorsHash\":\"\"' + parent_page_id_re = 'meta name=\"ajs-parent-page-id\" content=\"(.*?)\"' created_blog_title_re = 'anonymous_export_view.*?\"webui\":\"(.*?)\"' @@ -79,12 +81,7 @@ class CreateBlog(ConfluenceResource): class CreateEditPage(ConfluenceResource): action_name = 'create_and_edit_page' content_id_re = 'meta name=\"ajs-content-id\" content=\"(.*?)\">' - atl_token_re = 'meta name=\"ajs-atl-token\" content=\"(.*?)\">' - space_key_re = 'createpage.action\?spaceKey=(.+?)\&' - page_title_re = 'anonymous_export_view.*?\"webui\":\"(.*?)\"' - page_id_re = 'meta name=\"ajs-page-id\" content=\"(.*?)\">' parent_page_id = 'meta name=\"ajs-parent-page-id\" content=\"(.*?)\"' - create_page_id = 'meta name=\"ajs-page-id\" content=\"(.*?)\">' editor_page_title_re = 'name=\"ajs-page-title\" content=\"(.*?)\"' editor_page_version_re = 'name=\"ajs-page-version\" content=\"(.*?)\">' @@ -98,9 +95,24 @@ class CommentPage(ConfluenceResource): class UploadAttachments(ConfluenceResource): action_name = 'upload_attachments' - atl_token_view_issue_re = '"ajs-atl-token" content="(.+?)"' + + keyboard_hash_re = 'name=\"ajs-keyboardshortcut-hash\" content=\"(.*?)\">' + build_number_re = 'meta name=\"ajs-build-number\" content=\"(.*?)\"' + parent_page_id_re = 'meta name=\"ajs-parent-page-id\" content=\"(.*?)\"' class LikePage(ConfluenceResource): action_name = 'like_page' like_re = '\{\"likes\":\[\{"user":\{"name\"\:\"(.+?)",' + + +class ViewAttachment(ConfluenceResource): + action_name = 'view_attachment' + + keyboard_hash_re = 'name=\"ajs-keyboardshortcut-hash\" content=\"(.*?)\">' + build_number_re = 'meta name=\"ajs-build-number\" content=\"(.*?)\"' + parent_page_id_re = 'meta name=\"ajs-parent-page-id\" content=\"(.*?)\"' + remote_user_key_re = 'meta name=\"ajs-remote-user-key\" content=\"(.*?)\">' + data_linked_resource_id_re = 'data-linked-resource-id=\"(.*?)\"' + page_id_re = 'meta name=\"ajs-page-id\" content=\"(.*?)\">' + diff --git a/app/locustio/confluence/resources.json b/app/locustio/confluence/resources.json index 339813114..a29b52bb7 100644 --- a/app/locustio/confluence/resources.json +++ b/app/locustio/confluence/resources.json @@ -1,51 +1,65 @@ { "login_and_view_dashboard": { - "010": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","baseurl-checker-resource","dashboard","backbone-dashboard","atl.general","main"],"xr":["confluence.macros.advanced:blogpost-resources"]}, - "025": {"r":[],"c":["com.atlassian.confluence.extra.team-calendars.resources-batch"],"xc":["_super","baseurl-checker-resource","dashboard","backbone-dashboard","atl.general","main"],"xr":["confluence.macros.advanced:blogpost-resources"]} + "30": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","dashboard","backbone-dashboard","atl.general","main"],"xr":[]}, + "80": [{"name":"confluence.viewpage.src.empty","properties":{"userKey":"${ajs-remote-user-key}"},"timeDelta":-586},{"name":"confluence.spa.root-loaded","properties":{"redirectedTo":"all-updates","currentSection":""},"timeDelta":-568},{"name":"confluence.spa.rendered","properties":{"currentSection":"all-updates"},"timeDelta":-540},{"name":"confluence.spa.view","properties":{"previousSection":"all-updates","currentSection":"all-updates"},"timeDelta":-455}], + "90": [{"name":"browser.metrics.navigation","properties":{"apdex":"0","firstPaint":"10096","isInitial":"true","journeyId":"6925a014-c5e2-4fb6-a50b-671e1e5658de","key":"confluence.dashboard.view","navigationType":"0","readyForUser":"10702","redirectCount":"1","resourceLoadedEnd":"10044","resourceLoadedStart":9390.24999999674,"threshold":"1000","unloadEventStart":"9366","unloadEventEnd":"9366","redirectStart":"2","redirectEnd":"173","fetchStart":"173","domainLookupStart":"173","domainLookupEnd":"173","connectStart":"173","connectEnd":"173","requestStart":"176","responseStart":"333","responseEnd":"9360","domLoading":"9367","domInteractive":"10060","domContentLoadedEventStart":"10060","domContentLoadedEventEnd":"10091","domComplete":"10967","loadEventStart":"10967","loadEventEnd":"10968","userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36","serverDuration":"37","requestCorrelationId":"da8b3c3783e2a786","resourceTiming":"{\"☠\":[\"2,78u,7e2,7d1,799,78u,,78u,78u,78u\",\"2,78u,7e1,7cy,79a,78u,,78u,78u,78u\",\"2,78u,7e0,7cz,79a,78u,,78u,78u,78u\",\"3,78u,7lb,7d1,79b,78u,,78u,78u,78u\",\"3,78u,7r0,7gg,7cs,7cs,,79b,79b,79b\",\"3,78v,7hm,7gd,7cs,7cs,,79c,79c,79b\",\"5,7r9,7v1,7v0,7rb,7r9,,7r9,7r9,7r9\",\"4,7rm,7v8,7v7,7ro,7rm,,7rm,7rm,7rm\",\"4,7rp,7vb,7vb,7rr,7rp,,7rp,7rp,7rp\",\"4,7rq,7w7,7w5,7si,7rq,,7rq,7rq,7rq\",\"5,7tl,7xa,7x9,7tn,7tl,,7tl,7tl,7tl\",\"5,7tw,7xl,7xk,7tz,7tw,,7tw,7tw,7tw\",\"4,7um,7ys,7ys,7v9,7um,,7um,7um,7um\",\"4,7un,7yw,7yv,7vb,7un,,7un,7un,7un\",\"4,7uy,82h,82g,7yw,7uy,,7uy,7uy,7uy\",\"4,7uy,80z,80w,7xa,7uy,,7uy,7uy,7uy\",\"4,7uz,817,816,7xl,7uz,,7uz,7uz,7uz\",\"3,7v8,84u,84t,817,7v8,,7v8,7v8,7v8\",\"-1,7xo,82q,82p,7yt,7xo,,7xo,7xo,7xo\",\"5,80p,80s\",\"5,7ud,85x,85w,7v1,7ud,,7ud,7ud,7ud\"]}","mark.@grammarly-extension:checkScriptInitStart":"[10364]","mark.@grammarly-extension:checkScriptInitEnd":"[10371]","userTimingRaw":"{\"marks\":{\"@grammarly-extension:checkScriptInitStart\":[10364],\"@grammarly-extension:checkScriptInitEnd\":[10371]},\"measures\":{}}","experiments":"[]"},"timeDelta":-4690}] }, "view_page": { - "110": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","baseurl-checker-resource","atl.confluence.plugins.pagetree-desktop","main","viewcontent","page","atl.general","atl.comments"],"xr":[]}, - "145": {"r":[],"c":["request-access-plugin"],"xc":["_super","baseurl-checker-resource","atl.confluence.plugins.pagetree-desktop","main","viewcontent","page","atl.general","atl.comments"],"xr":[]}, - "150": {"r":[],"c":["editor-v4","editor","macro-browser","fullpage-editor"],"xc":["_super","baseurl-checker-resource","atl.confluence.plugins.pagetree-desktop","main","viewcontent","page","atl.general","atl.comments"],"xr":[]}, - "155": {"r":["confluence.web.resources.colors:colors","com.atlassian.confluence.keyboardshortcuts:confluence-keyboard-shortcuts","com.atlassian.confluence.editor:editor-resources-conf-frontend","com.atlassian.confluence.plugins.confluence-browser-metrics:editor","confluence.web.resources:quicksearchdropdown","com.atlassian.confluence.editor:property-panel-image-link-macro-conf-frontend","confluence.web.resources:legacy-editor-global-AVOID-IF-POSSIBLE","confluence.web.resources:hint-manager","confluence.web.resources:raphael","com.atlassian.confluence.plugins.confluence-link-browser:link-object","confluence.web.resources:core","com.atlassian.confluence.plugins.confluence-page-layout:pagelayout-frontend","com.atlassian.confluence.plugins.confluence-link-browser:link-browser-conf-frontend","confluence.extra.jira:macro-browser-resources","confluence.extra.jira:dialogsJs-for-conf-frontend","confluence.extra.jira:jirachart-macro","confluence.web.resources:navigator-context","com.atlassian.plugins.atlassian-connect-plugin:confluence-atlassian-connect-resources-v5","com.atlassian.plugins.atlassian-connect-plugin:dynamic-css-resources","com.atlassian.plugins.atlassian-connect-plugin:featured-macro-css-resources","com.atlassian.plugins.atlassian-connect-plugin:confluence-atlassian-connect-autoconvert-resources-v5","com.atlassian.plugins.atlassian-connect-plugin:macro-editor-resources-v5","com.atlassian.confluence.plugins.confluence-inline-tasks:editor-autocomplete-date-conf-frontend","confluence.web.resources:breadcrumbs","com.atlassian.confluence.plugins.confluence-collaborative-editor-plugin:confluence-collaborative-editor-plugin-resources","com.atlassian.confluence.keyboardshortcuts:confluence-keyboard-shortcuts","com.atlassian.confluence.plugins.confluence-labels:labels-editor","confluence.web.resources:ajs","com.atlassian.auiplugin:aui-inline-dialog2","confluence.web.resources:legacy-editor-global-AVOID-IF-POSSIBLE","com.atlassian.confluence.plugins.drag-and-drop:drag-and-drop-for-editor-conf-frontend","com.atlassian.confluence.plugins.gadgets:macro-browser-for-gadgetsplugin","com.atlassian.confluence.plugins.confluence-invite-to-edit:edit-resources","confluence.macros.multimedia:macro-browser-smart-fields","com.atlassian.confluence.editor:property-panel-image-link-macro-conf-frontend","com.atlassian.confluence.editor:property-panel-image-link-macro-conf-frontend","com.atlassian.confluence.image.effects.ImageEffectsPlugin:propertiespanel","com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-editor-resources-conf-frontend","com.atlassian.confluence.plugins.confluence-view-file-macro:view-file-macro-editor-resources","confluence.macros.advanced:editor_includemacro-conf-frontend","com.atlassian.confluence.plugins.confluence-request-access-plugin:confluence-request-access-plugin-resources","confluence.web.resources:deferred-dialog-loader","com.atlassian.confluence.plugins.confluence-create-content-plugin:editor-resources","com.atlassian.confluence.plugins.confluence-create-content-plugin:create-from-template-macro-browser-resources","com.atlassian.confluence.plugins.confluence-create-content-plugin:create-from-template-resources","com.atlassian.confluence.plugins.confluence-inline-tasks:inline-tasks-macro-browser","com.atlassian.confluence.extra.team-calendars:amd","com.atlassian.confluence.extra.team-calendars:user-timezone-setup","com.atlassian.confluence.extra.team-calendars:calendar-init-editor","com.atlassian.confluence.extra.team-calendars:macro-browser-web-resources","confluence.extra.jira:text-placeholders-jira"],"c":[],"xc":["_super","baseurl-checker-resource","atl.confluence.plugins.pagetree-desktop","main","viewcontent","page","atl.general","atl.comments"],"xr":[]}, - "160": {"r":[],"c":["com.atlassian.confluence.extra.team-calendars.resources-batch"],"xc":["_super","baseurl-checker-resource","atl.confluence.plugins.pagetree-desktop","main","viewcontent","page","atl.general","atl.comments"],"xr":[]} + "110": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","atl.confluence.plugins.pagetree-desktop","main","viewcontent","atl.general","page","atl.comments"],"xr":[]}, + "200": {"r":[],"c":["sortable-tables-resources","request-access-plugin"],"xc":["_super","atl.confluence.plugins.pagetree-desktop","main","viewcontent","atl.general","page","atl.comments","browser-metrics-plugin.contrib"],"xr":[]}, + "220": [{"name":"confluence.viewpage.src.empty","properties":{"userKey":"${ajs-remote-user-key}","pageID":"${page_id}"},"timeDelta":-510},{"name":"confluence.page.view","properties":{"pageID":"${page_id}"},"timeDelta":-502},{"name":"browser.metrics.navigation","properties":{"apdex":"0.5","firstPaint":"1138","isInitial":"true","journeyId":"a7c0ccb4-dcf5-46b1-b640-5dda29da5764","key":"confluence.page.view","navigationType":"1","readyForUser":"1232","redirectCount":"0","resourceLoadedEnd":"899","resourceLoadedStart":237.04499999985273,"threshold":"1000","unloadEventStart":"213","unloadEventEnd":"213","fetchStart":"0","domainLookupStart":"0","domainLookupEnd":"0","connectStart":"0","connectEnd":"0","requestStart":"5","responseStart":"201","responseEnd":"219","domLoading":"217","domInteractive":"1071","domContentLoadedEventStart":"1071","domContentLoadedEventEnd":"1098","domComplete":"1540","loadEventStart":"1541","loadEventEnd":"1545","userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36","serverDuration":"78","requestCorrelationId":"2e7b1dbf229e6734","resourceTiming":"{\"☠\":[\"2,6l,hl,aj,6w,6l,,6l,6l,6l\",\"2,6l,e5,am,6x,6l,,6l,6l,6l\",\"3,6l,oz,an,6x,6l,,6l,6l,6l\",\"3,6l,lf,ap,6x,6l,,6l,6l,6l\",\"5,re,v6,v6,rg,re,,re,re,re\",\"5,rk,v8,v7,rm,rk,,rk,rk,rk\",\"4,sd,we,wd,st,sd,,sd,sd,sd\"]}","userTimingRaw":"{\"marks\":{},\"measures\":{}}","experiments":"[]"},"timeDelta":-154}], + "230": {"r":[],"c":["editor-v4","editor","macro-browser","fullpage-editor"],"xc":["_super","atl.confluence.plugins.pagetree-desktop","main","viewcontent","atl.general","page","atl.comments","browser-metrics-plugin.contrib","sortable-tables-resources","request-access-plugin"],"xr":[]} }, "view_dashboard": { - "205": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","baseurl-checker-resource","dashboard","backbone-dashboard","atl.general","main"],"xr":["confluence.macros.advanced:blogpost-resources"]}, - "220": {"r":[],"c":["com.atlassian.confluence.extra.team-calendars.resources-batch"],"xc":["_super","baseurl-checker-resource","dashboard","backbone-dashboard","atl.general","main"],"xr":["confluence.macros.advanced:blogpost-resources"]} + "280": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","dashboard","backbone-dashboard","atl.general","main"],"xr":[]}, + "330": [{"name":"confluence.viewpage.src.empty","properties":{"userKey":"${ajs-remote-user-key}"},"timeDelta":-617},{"name":"confluence.spa.root-loaded","properties":{"redirectedTo":"all-updates","currentSection":""},"timeDelta":-597},{"name":"confluence.spa.rendered","properties":{"currentSection":"all-updates"},"timeDelta":-556},{"name":"confluence.spa.view","properties":{"previousSection":"all-updates","currentSection":"all-updates"},"timeDelta":-475},{"name":"browser.metrics.navigation","properties":{"apdex":"0.5","firstPaint":"943","isInitial":"true","journeyId":"a7c0ccb4-dcf5-46b1-b640-5dda29da5764","key":"confluence.dashboard.view","navigationType":"0","readyForUser":"1560","redirectCount":"0","resourceLoadedEnd":"828","resourceLoadedStart":184.42499998491257,"threshold":"1000","unloadEventStart":"164","unloadEventEnd":"164","fetchStart":"1","domainLookupStart":"1","domainLookupEnd":"1","connectStart":"1","connectEnd":"1","requestStart":"4","responseStart":"160","responseEnd":"172","domLoading":"166","domInteractive":"903","domContentLoadedEventStart":"903","domContentLoadedEventEnd":"933","domComplete":"1362","loadEventStart":"1362","loadEventEnd":"1363","userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36","serverDuration":"40","requestCorrelationId":"cd97183c29eb2d82","resourceTiming":"{\"☠\":[\"2,54,cn,93,5f,54,,54,54,54\",\"2,54,97,94,5i,54,,54,54,54\",\"2,54,92,91,5i,54,,54,54,54\",\"3,54,n0,96,5i,54,,54,54,54\",\"3,55,gb,9c,5i,55,,55,55,55\",\"3,55,94,93,5j,55,,55,55,55\",\"5,ow,sm,sm,oy,ow,,ow,ow,ow\",\"4,p9,sv,su,pb,p9,,p9,p9,p9\",\"4,pc,sy,sy,pe,pc,,pc,pc,pc\",\"4,pd,tt,tq,q3,pd,,pd,pd,pd\",\"5,r0,um,ul,r2,r0,,r0,r0,r0\",\"5,r9,uu,ut,rb,r9,,r9,r9,r9\",\"4,sd,we,we,sv,sd,,sd,sd,sd\",\"4,sd,wh,wg,sz,sd,,sd,sd,sd\",\"4,ss,y6,y6,um,ss,,ss,ss,ss\",\"4,ss,zz,zy,wf,ss,,ss,ss,ss\",\"4,ss,yf,yf,uu,ss,,ss,ss,ss\",\"3,t8,11s,11q,y7,t8,,t8,t8,t8\",\"5,yx,z2\",\"5,rx,13l,13k,sm,rx,,rx,rx,rx\"]}","mark.@grammarly-extension:checkScriptInitStart":"[1207]","mark.@grammarly-extension:checkScriptInitEnd":"[1212]","userTimingRaw":"{\"marks\":{\"@grammarly-extension:checkScriptInitStart\":[1207],\"@grammarly-extension:checkScriptInitEnd\":[1212]},\"measures\":{}}","experiments":"[]"},"timeDelta":-26}] }, "view_blog": { - "310": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","baseurl-checker-resource","atl.confluence.plugins.pagetree-desktop","main","viewcontent","page","atl.general","atl.comments"],"xr":[]}, - "345": {"r":[],"c":["request-access-plugin"],"xc":["_super","baseurl-checker-resource","atl.confluence.plugins.pagetree-desktop","main","viewcontent","page","atl.general","atl.comments"],"xr":[]}, - "350": {"r":[],"c":["editor-v4","editor","macro-browser","fullpage-editor"],"xc":["_super","baseurl-checker-resource","atl.confluence.plugins.pagetree-desktop","main","viewcontent","page","atl.general","atl.comments"],"xr":[]}, - "355": {"r":["confluence.web.resources.colors:colors","com.atlassian.confluence.keyboardshortcuts:confluence-keyboard-shortcuts","com.atlassian.confluence.editor:editor-resources-conf-frontend","com.atlassian.confluence.plugins.confluence-browser-metrics:editor","confluence.web.resources:quicksearchdropdown","com.atlassian.confluence.editor:property-panel-image-link-macro-conf-frontend","confluence.web.resources:legacy-editor-global-AVOID-IF-POSSIBLE","confluence.web.resources:hint-manager","confluence.web.resources:raphael","com.atlassian.confluence.plugins.confluence-link-browser:link-object","confluence.web.resources:core","com.atlassian.confluence.plugins.confluence-page-layout:pagelayout-frontend","com.atlassian.confluence.plugins.confluence-link-browser:link-browser-conf-frontend","confluence.extra.jira:macro-browser-resources","confluence.extra.jira:dialogsJs-for-conf-frontend","confluence.extra.jira:jirachart-macro","confluence.web.resources:navigator-context","com.atlassian.plugins.atlassian-connect-plugin:confluence-atlassian-connect-resources-v5","com.atlassian.plugins.atlassian-connect-plugin:dynamic-css-resources","com.atlassian.plugins.atlassian-connect-plugin:featured-macro-css-resources","com.atlassian.plugins.atlassian-connect-plugin:confluence-atlassian-connect-autoconvert-resources-v5","com.atlassian.plugins.atlassian-connect-plugin:macro-editor-resources-v5","com.atlassian.confluence.plugins.confluence-inline-tasks:editor-autocomplete-date-conf-frontend","confluence.web.resources:breadcrumbs","com.atlassian.confluence.plugins.confluence-collaborative-editor-plugin:confluence-collaborative-editor-plugin-resources","com.atlassian.confluence.keyboardshortcuts:confluence-keyboard-shortcuts","com.atlassian.confluence.plugins.confluence-labels:labels-editor","confluence.web.resources:ajs","com.atlassian.auiplugin:aui-inline-dialog2","confluence.web.resources:legacy-editor-global-AVOID-IF-POSSIBLE","com.atlassian.confluence.plugins.drag-and-drop:drag-and-drop-for-editor-conf-frontend","com.atlassian.confluence.plugins.gadgets:macro-browser-for-gadgetsplugin","com.atlassian.confluence.plugins.confluence-invite-to-edit:edit-resources","confluence.macros.multimedia:macro-browser-smart-fields","com.atlassian.confluence.editor:property-panel-image-link-macro-conf-frontend","com.atlassian.confluence.editor:property-panel-image-link-macro-conf-frontend","com.atlassian.confluence.image.effects.ImageEffectsPlugin:propertiespanel","com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-editor-resources-conf-frontend","com.atlassian.confluence.plugins.confluence-view-file-macro:view-file-macro-editor-resources","confluence.macros.advanced:editor_includemacro-conf-frontend","com.atlassian.confluence.plugins.confluence-request-access-plugin:confluence-request-access-plugin-resources","confluence.web.resources:deferred-dialog-loader","com.atlassian.confluence.plugins.confluence-create-content-plugin:editor-resources","com.atlassian.confluence.plugins.confluence-create-content-plugin:create-from-template-macro-browser-resources","com.atlassian.confluence.plugins.confluence-create-content-plugin:create-from-template-resources","com.atlassian.confluence.plugins.confluence-inline-tasks:inline-tasks-macro-browser","com.atlassian.confluence.extra.team-calendars:amd","com.atlassian.confluence.extra.team-calendars:user-timezone-setup","com.atlassian.confluence.extra.team-calendars:calendar-init-editor","com.atlassian.confluence.extra.team-calendars:macro-browser-web-resources","confluence.extra.jira:text-placeholders-jira"],"c":[],"xc":["_super","baseurl-checker-resource","atl.confluence.plugins.pagetree-desktop","main","viewcontent","page","atl.general","atl.comments"],"xr":[]}, - "360": {"r":[],"c":["com.atlassian.confluence.extra.team-calendars.resources-batch"],"xc":["_super","baseurl-checker-resource","atl.confluence.plugins.pagetree-desktop","main","viewcontent","page","atl.general","atl.comments"],"xr":[]} + "350": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","blogpost","viewcontent","main","atl.general","atl.comments"],"xr":[]}, + "430": [{"name":"confluence.viewpage.src.empty","properties":{"userKey":"${ajs-remote-user-key}","pageID":"${blog_id}"},"timeDelta":-502}], + "440": {"r":["com.atlassian.confluence.ext.newcode-macro-plugin:sh-theme-confluence","com.atlassian.confluence.ext.newcode-macro-plugin:sh-theme-confluence"],"c":["request-access-plugin","sortable-tables-resources","code-macro"],"xc":["_super","blogpost","viewcontent","main","atl.general","atl.comments","browser-metrics-plugin.contrib"],"xr":[]}, + "480": {"r":[],"c":["editor-v4","editor","macro-browser","fullpage-editor"],"xc":["_super","blogpost","viewcontent","main","atl.general","atl.comments","browser-metrics-plugin.contrib","request-access-plugin","sortable-tables-resources","code-macro"],"xr":["com.atlassian.confluence.ext.newcode-macro-plugin:sh-theme-confluence"]} }, "create_blog": { - "910": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","baseurl-checker-resource","editor-v4","atl.general","editor","macro-browser","main","blogpost"],"xr":["com.atlassian.confluence.plugins.confluence-space-ia:spacesidebar"]}, - "925": {"r":[],"c":["com.atlassian.confluence.extra.team-calendars.resources-batch"],"xc":["_super","baseurl-checker-resource","editor-v4","atl.general","editor","macro-browser","main","blogpost"],"xr":["com.atlassian.confluence.plugins.confluence-space-ia:spacesidebar"]}, - "930": {"r":[],"c":["request-access-plugin"],"xc":["_super","baseurl-checker-resource","editor-v4","atl.general","editor","macro-browser","main","blogpost"],"xr":["com.atlassian.confluence.plugins.confluence-space-ia:spacesidebar"]}, - "970": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","baseurl-checker-resource","blogpost","viewcontent","main","atl.general","atl.comments"],"xr":[]}, - "975": {"r":[],"c":["sortable-tables-resources"],"xc":["_super","baseurl-checker-resource","blogpost","viewcontent","main","atl.general","atl.comments"],"xr":[]}, - "995": {"r":[],"c":["request-access-plugin"],"xc":["_super","baseurl-checker-resource","blogpost","viewcontent","main","atl.general","atl.comments"],"xr":[]}, - "1030": {"r":[],"c":["editor-v4","editor","macro-browser","fullpage-editor"],"xc":["_super","baseurl-checker-resource","blogpost","viewcontent","main","atl.general","atl.comments"],"xr":[]}, - "1035": {"r":[],"c":["com.atlassian.confluence.extra.team-calendars.resources-batch"],"xc":["_super","baseurl-checker-resource","blogpost","viewcontent","main","atl.general","atl.comments"],"xr":[]} + "560": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","editor-v4","atl.general","editor","macro-browser","main","blogpost"],"xr":["com.atlassian.confluence.plugins.confluence-space-ia:spacesidebar"]}, + "700": {"r":[],"c":["request-access-plugin"],"xc":["_super","editor-v4","atl.general","editor","macro-browser","main","blogpost","browser-metrics-plugin.contrib"],"xr":["com.atlassian.confluence.plugins.confluence-space-ia:spacesidebar","com.atlassian.confluence.plugins.confluence-space-ia:soy-resources"]}, + "730": [{"name":"confluence.editor.close","properties":{"source":"publishButton"},"timeDelta":-25},{"name":"confluence.table.quality.in.page","properties":{"pageId":"${ajs-page-id}","total":0,"fixed":0,"fluid":0,"relative":0,"nested":0},"timeDelta":-23}], + "740": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","blogpost","viewcontent","main","atl.general","atl.comments"],"xr":[]}, + "830": {"r":[],"c":["request-access-plugin"],"xc":["_super","blogpost","viewcontent","main","atl.general","atl.comments","browser-metrics-plugin.contrib"],"xr":[]}, + "850": [{"name":"confluence.viewpage.src.empty","properties":{"userKey":"${ajs-remote-user-key}","pageID":"${ajs-page-id}","draftID":"${ajs-draft-id}"},"timeDelta":-609},{"name":"confluence.editor.ready.collab.mode.on","properties":{"connectionOrder":"","connectionType":""},"timeDelta":-255}], + "880": [{"name":"confluence.synchrony.editor.loaded","properties":{"durationMillis":877,"contentId":"${ajs-content-id}"},"timeDelta":-4514},{"name":"browser.metrics.navigation","properties":{"apdex":"0.5","firstPaint":"2578","isInitial":"true","journeyId":"a7c0ccb4-dcf5-46b1-b640-5dda29da5764","key":"confluence.blogpost.create.collaborative.view","navigationType":"0","readyForUser":"3862","redirectCount":"0","resourceLoadedEnd":"2344","resourceLoadedStart":315.84500009194016,"threshold":"1000","unloadEventStart":"292","unloadEventEnd":"292","fetchStart":"2","domainLookupStart":"2","domainLookupEnd":"2","connectStart":"2","connectEnd":"2","requestStart":"5","responseStart":"284","responseEnd":"432","domLoading":"293","domInteractive":"2553","domContentLoadedEventStart":"2553","domContentLoadedEventEnd":"2563","domComplete":"3785","loadEventStart":"3785","loadEventEnd":"3786","userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36","serverDuration":"64","requestCorrelationId":"3dfaa599735fcbcb","resourceTiming":"{\"☠\":[\"2,8r,h3,gy,94,8r,,8r,8r,8r\",\"2,8s,qz,gy,96,8s,,8s,8s,8s\",\"2,8s,h1,gx,96,8s,,8s,8s,8s\",\"3,8s,102,gy,96,8s,,8s,8s,8s\",\"3,8s,1t4,gy,96,8s,,8s,8s,8s\",\"3,8s,1ez,14y,c0,8s,,8s,8s,8s\",\"3,8s,lz,ly,h1,8s,,8s,8s,8s\",\"5,1vg,22n,224,1vh,1vg,,1vg,1vg,1vg\",\"5,1vm,21m,21m,1vp,1vm,,1vm,1vm,1vm\",\"4,1xf,21h,21g,1xg,1xf,,1xf,1xf,1xf\",\"4,1xg,236,232,1zj,1xg,,1xg,1xg,1xg\",\"5,20u,24h,24g,20w,20u,,20u,20u,20u\",\"5,20w,24r,24p,211,20w,,20w,20w,20w\",\"5,219,254,253,21h,219,,219,219,219\",\"5,235,26r,26q,237,235,,235,235,235\",\"3,276,2at,2ar,277,276,,276,276,276\",\"5,277,2as,2as,278,277,,277,277,277\",\"5,2a8,2e4,2e3,2aa,2a8,,2a8,2a8,2a8\",\"5,2ac,2dy,2dy,2ae,2ac,,2ac,2ac,2ac\",\"5,2ag,2ed,2ed,2at,2ag,,2ag,2ag,2ag\",\"5,2iq,2jh\",\"5,2h7,2lm,2lm,2hm,2h7,,2h7,2h7,2h7\",\"5,2hk,2lf,2lf,2ho,2hk,,2hk,2hk,2hk\",\"5,2hv,2lj,2lj,2hz,2hv,,2hv,2hv,2hv\",\"5,2i6,2m7,2m5,2im,2i6,,2i6,2i6,2i6\",\"5,2i9,2td,2m6,2in,2i9,,2i9,2i9,2i9\",\"5,2j9,2o4,2o3,2kf,2j9,,2j9,2j9,2j9\",\"2,2o7,2so,2sl,2p1,2o7,,2o7,2o7,2o7\",\"3,2o7,2x4,2x3,2tj,2o7,,2o7,2o7,2o7\",\"5,2uj,2yu,2yu,2v9,2uj,,2uj,2uj,2uj\"]}","mark.@grammarly-extension:checkScriptInitStart":"[3196]","mark.@grammarly-extension:checkScriptInitEnd":"[3198]","userTimingRaw":"{\"marks\":{\"@grammarly-extension:checkScriptInitStart\":[3196],\"@grammarly-extension:checkScriptInitEnd\":[3198]},\"measures\":{}}","experiments":"[]"},"timeDelta":-4501},{"name":"confluence.synchrony.user.in.session","properties":{"numOtherUsers":1,"draftId":"38904812","contentId":"38904812"},"timeDelta":-3368},{"name":"browser.metrics.navigation","properties":{"apdex":"0.5","isInitial":"false","journeyId":"a7c0ccb4-dcf5-46b1-b640-5dda29da5764","key":"confluence.blogpost.create.collaborative.view.connected","readyForUser":"1139","threshold":"1000","userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36","resourceTiming":"{\"☠\":[\"5,dv,dy\"]}","userTimingRaw":"{\"marks\":{},\"measures\":{}}","experiments":"[]"},"timeDelta":-3365}], + "890": [{"name":"confluence.viewpage.src.empty","properties":{"userKey":"${ajs-remote-user-key}","pageID":"${page_id}"},"timeDelta":-502},{"name":"browser.metrics.navigation","properties":{"apdex":"0.5","firstPaint":"1377","isInitial":"true","journeyId":"a7c0ccb4-dcf5-46b1-b640-5dda29da5764","key":"confluence.blogpost.view","navigationType":"0","readyForUser":"1441","redirectCount":"0","resourceLoadedEnd":"1297","resourceLoadedStart":269.0850000362843,"threshold":"1000","unloadEventStart":"247","unloadEventEnd":"247","fetchStart":"5","domainLookupStart":"5","domainLookupEnd":"5","connectStart":"5","connectEnd":"5","requestStart":"14","responseStart":"236","responseEnd":"249","domLoading":"251","domInteractive":"1363","domContentLoadedEventStart":"1363","domContentLoadedEventEnd":"1370","domComplete":"1734","loadEventStart":"1735","loadEventEnd":"1738","userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36","serverDuration":"107","requestCorrelationId":"edf885c57119f2bd","resourceTiming":"{\"☠\":[\"2,7h,bq,bc,7r,7h,,7h,7h,7h\",\"2,7h,bo,be,7r,7h,,7h,7h,7h\",\"3,7h,lu,bh,7s,7h,,7h,7h,7h\",\"3,7h,101,bj,7s,7h,,7h,7h,7h\"]}","userTimingRaw":"{\"marks\":{},\"measures\":{}}","experiments":"[]"},"timeDelta":-176}], + "910": {"r":[],"c":["editor-v4","editor","macro-browser","fullpage-editor"],"xc":["_super","blogpost","viewcontent","main","atl.general","atl.comments","browser-metrics-plugin.contrib","request-access-plugin"],"xr":[]} }, "create_and_edit_page": { - "705": {"r":["confluence.web.resources.colors:colors","com.atlassian.confluence.keyboardshortcuts:confluence-keyboard-shortcuts","com.atlassian.confluence.editor:editor-resources-conf-frontend","com.atlassian.confluence.plugins.confluence-browser-metrics:editor","confluence.web.resources:quicksearchdropdown","com.atlassian.confluence.editor:property-panel-image-link-macro-conf-frontend","confluence.web.resources:legacy-editor-global-AVOID-IF-POSSIBLE","confluence.web.resources:hint-manager","confluence.web.resources:raphael","com.atlassian.confluence.plugins.confluence-link-browser:link-object","confluence.web.resources:core","com.atlassian.confluence.plugins.confluence-page-layout:pagelayout-frontend","com.atlassian.confluence.plugins.confluence-link-browser:link-browser-conf-frontend","confluence.extra.jira:macro-browser-resources","confluence.extra.jira:dialogsJs-for-conf-frontend","confluence.extra.jira:jirachart-macro","confluence.web.resources:navigator-context","com.atlassian.plugins.atlassian-connect-plugin:confluence-atlassian-connect-resources-v5","com.atlassian.plugins.atlassian-connect-plugin:dynamic-css-resources","com.atlassian.plugins.atlassian-connect-plugin:featured-macro-css-resources","com.atlassian.plugins.atlassian-connect-plugin:confluence-atlassian-connect-autoconvert-resources-v5","com.atlassian.plugins.atlassian-connect-plugin:macro-editor-resources-v5","com.atlassian.confluence.plugins.confluence-inline-tasks:editor-autocomplete-date-conf-frontend","confluence.web.resources:breadcrumbs","com.atlassian.confluence.plugins.confluence-collaborative-editor-plugin:confluence-collaborative-editor-plugin-resources","com.atlassian.confluence.keyboardshortcuts:confluence-keyboard-shortcuts","com.atlassian.confluence.plugins.confluence-labels:labels-editor","confluence.web.resources:ajs","com.atlassian.auiplugin:aui-inline-dialog2","confluence.web.resources:legacy-editor-global-AVOID-IF-POSSIBLE","com.atlassian.confluence.plugins.drag-and-drop:drag-and-drop-for-editor-conf-frontend","com.atlassian.confluence.plugins.gadgets:macro-browser-for-gadgetsplugin","com.atlassian.confluence.plugins.confluence-invite-to-edit:edit-resources","confluence.macros.multimedia:macro-browser-smart-fields","com.atlassian.confluence.editor:property-panel-image-link-macro-conf-frontend","com.atlassian.confluence.editor:property-panel-image-link-macro-conf-frontend","com.atlassian.confluence.image.effects.ImageEffectsPlugin:propertiespanel","com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-editor-resources-conf-frontend","com.atlassian.confluence.plugins.confluence-view-file-macro:view-file-macro-editor-resources","confluence.macros.advanced:editor_includemacro-conf-frontend","com.atlassian.confluence.plugins.confluence-request-access-plugin:confluence-request-access-plugin-resources","confluence.web.resources:deferred-dialog-loader","com.atlassian.confluence.plugins.confluence-create-content-plugin:editor-resources","com.atlassian.confluence.plugins.confluence-create-content-plugin:create-from-template-macro-browser-resources","com.atlassian.confluence.plugins.confluence-create-content-plugin:create-from-template-resources","com.atlassian.confluence.plugins.confluence-inline-tasks:inline-tasks-macro-browser","com.atlassian.confluence.extra.team-calendars:amd","com.atlassian.confluence.extra.team-calendars:user-timezone-setup","com.atlassian.confluence.extra.team-calendars:calendar-init-editor","com.atlassian.confluence.extra.team-calendars:macro-browser-web-resources","confluence.extra.jira:text-placeholders-jira"],"c":[],"xc":["_super","baseurl-checker-resource","editor-v4","editor","macro-browser","atl.general","main","page"],"xr":["com.atlassian.confluence.plugins.confluence-space-ia:spacesidebar"]}, - "710": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","baseurl-checker-resource","editor-v4","editor","macro-browser","atl.general","main","page"],"xr":["com.atlassian.confluence.plugins.confluence-space-ia:spacesidebar"]}, - "715": {"r":[],"c":["com.atlassian.confluence.extra.team-calendars.resources-batch"],"xc":["_super","baseurl-checker-resource","editor-v4","editor","macro-browser","atl.general","main","page"],"xr":["com.atlassian.confluence.plugins.confluence-space-ia:spacesidebar"]}, - "750": {"r":[],"c":["request-access-plugin"],"xc":["_super","baseurl-checker-resource","editor-v4","editor","macro-browser","atl.general","main","page"],"xr":["com.atlassian.confluence.plugins.confluence-space-ia:spacesidebar"]}, - "795": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","baseurl-checker-resource","atl.confluence.plugins.pagetree-desktop","main","viewcontent","page","atl.general","atl.comments"],"xr":[]}, - "830": {"r":[],"c":["sortable-tables-resources"],"xc":["_super","baseurl-checker-resource","atl.confluence.plugins.pagetree-desktop","main","viewcontent","page","atl.general","atl.comments"],"xr":[]}, - "835": {"r":[],"c":["request-access-plugin"],"xc":["_super","baseurl-checker-resource","atl.confluence.plugins.pagetree-desktop","main","viewcontent","page","atl.general","atl.comments"],"xr":[]}, - "845": {"r":[],"c":["editor-v4","editor","macro-browser","fullpage-editor"],"xc":["_super","baseurl-checker-resource","atl.confluence.plugins.pagetree-desktop","main","viewcontent","page","atl.general","atl.comments"],"xr":[]}, - "850": {"r":["confluence.web.resources.colors:colors","com.atlassian.confluence.keyboardshortcuts:confluence-keyboard-shortcuts","com.atlassian.confluence.editor:editor-resources-conf-frontend","com.atlassian.confluence.plugins.confluence-browser-metrics:editor","confluence.web.resources:quicksearchdropdown","com.atlassian.confluence.editor:property-panel-image-link-macro-conf-frontend","confluence.web.resources:legacy-editor-global-AVOID-IF-POSSIBLE","confluence.web.resources:hint-manager","confluence.web.resources:raphael","com.atlassian.confluence.plugins.confluence-link-browser:link-object","confluence.web.resources:core","com.atlassian.confluence.plugins.confluence-page-layout:pagelayout-frontend","com.atlassian.confluence.plugins.confluence-link-browser:link-browser-conf-frontend","confluence.extra.jira:macro-browser-resources","confluence.extra.jira:dialogsJs-for-conf-frontend","confluence.extra.jira:jirachart-macro","confluence.web.resources:navigator-context","com.atlassian.plugins.atlassian-connect-plugin:confluence-atlassian-connect-resources-v5","com.atlassian.plugins.atlassian-connect-plugin:dynamic-css-resources","com.atlassian.plugins.atlassian-connect-plugin:featured-macro-css-resources","com.atlassian.plugins.atlassian-connect-plugin:confluence-atlassian-connect-autoconvert-resources-v5","com.atlassian.plugins.atlassian-connect-plugin:macro-editor-resources-v5","com.atlassian.confluence.plugins.confluence-inline-tasks:editor-autocomplete-date-conf-frontend","confluence.web.resources:breadcrumbs","com.atlassian.confluence.plugins.confluence-collaborative-editor-plugin:confluence-collaborative-editor-plugin-resources","com.atlassian.confluence.keyboardshortcuts:confluence-keyboard-shortcuts","com.atlassian.confluence.plugins.confluence-labels:labels-editor","confluence.web.resources:ajs","com.atlassian.auiplugin:aui-inline-dialog2","confluence.web.resources:legacy-editor-global-AVOID-IF-POSSIBLE","com.atlassian.confluence.plugins.drag-and-drop:drag-and-drop-for-editor-conf-frontend","com.atlassian.confluence.plugins.gadgets:macro-browser-for-gadgetsplugin","com.atlassian.confluence.plugins.confluence-invite-to-edit:edit-resources","confluence.macros.multimedia:macro-browser-smart-fields","com.atlassian.confluence.editor:property-panel-image-link-macro-conf-frontend","com.atlassian.confluence.editor:property-panel-image-link-macro-conf-frontend","com.atlassian.confluence.image.effects.ImageEffectsPlugin:propertiespanel","com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-editor-resources-conf-frontend","com.atlassian.confluence.plugins.confluence-view-file-macro:view-file-macro-editor-resources","confluence.macros.advanced:editor_includemacro-conf-frontend","com.atlassian.confluence.plugins.confluence-request-access-plugin:confluence-request-access-plugin-resources","confluence.web.resources:deferred-dialog-loader","com.atlassian.confluence.plugins.confluence-create-content-plugin:editor-resources","com.atlassian.confluence.plugins.confluence-create-content-plugin:create-from-template-macro-browser-resources","com.atlassian.confluence.plugins.confluence-create-content-plugin:create-from-template-resources","com.atlassian.confluence.plugins.confluence-inline-tasks:inline-tasks-macro-browser","com.atlassian.confluence.extra.team-calendars:amd","com.atlassian.confluence.extra.team-calendars:user-timezone-setup","com.atlassian.confluence.extra.team-calendars:calendar-init-editor","com.atlassian.confluence.extra.team-calendars:macro-browser-web-resources","confluence.extra.jira:text-placeholders-jira"],"c":[],"xc":["_super","baseurl-checker-resource","atl.confluence.plugins.pagetree-desktop","main","viewcontent","page","atl.general","atl.comments"],"xr":[]}, - "855": {"r":[],"c":["com.atlassian.confluence.extra.team-calendars.resources-batch"],"xc":["_super","baseurl-checker-resource","atl.confluence.plugins.pagetree-desktop","main","viewcontent","page","atl.general","atl.comments"],"xr":[]}, - "1175": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","baseurl-checker-resource","atl.confluence.plugins.pagetree-desktop","main","viewcontent","page","atl.general","atl.comments"],"xr":[]}, - "1215": {"r":[],"c":["request-access-plugin"],"xc":["_super","baseurl-checker-resource","atl.confluence.plugins.pagetree-desktop","main","viewcontent","page","atl.general","atl.comments"],"xr":[]}, - "1220": {"r":[],"c":["editor-v4","editor","macro-browser","fullpage-editor"],"xc":["_super","baseurl-checker-resource","atl.confluence.plugins.pagetree-desktop","main","viewcontent","page","atl.general","atl.comments"],"xr":[]}, - "1225": {"r":["confluence.web.resources.colors:colors","com.atlassian.confluence.keyboardshortcuts:confluence-keyboard-shortcuts","com.atlassian.confluence.editor:editor-resources-conf-frontend","com.atlassian.confluence.plugins.confluence-browser-metrics:editor","confluence.web.resources:quicksearchdropdown","com.atlassian.confluence.editor:property-panel-image-link-macro-conf-frontend","confluence.web.resources:legacy-editor-global-AVOID-IF-POSSIBLE","confluence.web.resources:hint-manager","confluence.web.resources:raphael","com.atlassian.confluence.plugins.confluence-link-browser:link-object","confluence.web.resources:core","com.atlassian.confluence.plugins.confluence-page-layout:pagelayout-frontend","com.atlassian.confluence.plugins.confluence-link-browser:link-browser-conf-frontend","confluence.extra.jira:macro-browser-resources","confluence.extra.jira:dialogsJs-for-conf-frontend","confluence.extra.jira:jirachart-macro","confluence.web.resources:navigator-context","com.atlassian.plugins.atlassian-connect-plugin:confluence-atlassian-connect-resources-v5","com.atlassian.plugins.atlassian-connect-plugin:dynamic-css-resources","com.atlassian.plugins.atlassian-connect-plugin:featured-macro-css-resources","com.atlassian.plugins.atlassian-connect-plugin:confluence-atlassian-connect-autoconvert-resources-v5","com.atlassian.plugins.atlassian-connect-plugin:macro-editor-resources-v5","com.atlassian.confluence.plugins.confluence-inline-tasks:editor-autocomplete-date-conf-frontend","confluence.web.resources:breadcrumbs","com.atlassian.confluence.plugins.confluence-collaborative-editor-plugin:confluence-collaborative-editor-plugin-resources","com.atlassian.confluence.keyboardshortcuts:confluence-keyboard-shortcuts","com.atlassian.confluence.plugins.confluence-labels:labels-editor","confluence.web.resources:ajs","com.atlassian.auiplugin:aui-inline-dialog2","confluence.web.resources:legacy-editor-global-AVOID-IF-POSSIBLE","com.atlassian.confluence.plugins.drag-and-drop:drag-and-drop-for-editor-conf-frontend","com.atlassian.confluence.plugins.gadgets:macro-browser-for-gadgetsplugin","com.atlassian.confluence.plugins.confluence-invite-to-edit:edit-resources","confluence.macros.multimedia:macro-browser-smart-fields","com.atlassian.confluence.editor:property-panel-image-link-macro-conf-frontend","com.atlassian.confluence.editor:property-panel-image-link-macro-conf-frontend","com.atlassian.confluence.image.effects.ImageEffectsPlugin:propertiespanel","com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-editor-resources-conf-frontend","com.atlassian.confluence.plugins.confluence-view-file-macro:view-file-macro-editor-resources","confluence.macros.advanced:editor_includemacro-conf-frontend","com.atlassian.confluence.plugins.confluence-request-access-plugin:confluence-request-access-plugin-resources","confluence.web.resources:deferred-dialog-loader","com.atlassian.confluence.plugins.confluence-create-content-plugin:editor-resources","com.atlassian.confluence.plugins.confluence-create-content-plugin:create-from-template-macro-browser-resources","com.atlassian.confluence.plugins.confluence-create-content-plugin:create-from-template-resources","com.atlassian.confluence.plugins.confluence-inline-tasks:inline-tasks-macro-browser","com.atlassian.confluence.extra.team-calendars:amd","com.atlassian.confluence.extra.team-calendars:user-timezone-setup","com.atlassian.confluence.extra.team-calendars:calendar-init-editor","com.atlassian.confluence.extra.team-calendars:macro-browser-web-resources","confluence.extra.jira:text-placeholders-jira"],"c":[],"xc":["_super","baseurl-checker-resource","atl.confluence.plugins.pagetree-desktop","main","viewcontent","page","atl.general","atl.comments"],"xr":[]}, - "1230": {"r":[],"c":["com.atlassian.confluence.extra.team-calendars.resources-batch"],"xc":["_super","baseurl-checker-resource","atl.confluence.plugins.pagetree-desktop","main","viewcontent","page","atl.general","atl.comments"],"xr":[]} + "970": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","editor-v4","atl.general","editor","macro-browser","main","page"],"xr":["com.atlassian.confluence.plugins.confluence-space-ia:spacesidebar"]}, + "1100": {"r":[],"c":["request-access-plugin"],"xc":["_super","editor-v4","atl.general","editor","macro-browser","main","page","browser-metrics-plugin.contrib"],"xr":["com.atlassian.confluence.plugins.confluence-space-ia:spacesidebar","com.atlassian.confluence.plugins.confluence-space-ia:soy-resources"]}, + "1110": [{"name":"confluence.synchrony.exit.before.connecting","properties":{"afterTimeout":false,"contentId":"${ajs-content-id}"},"timeDelta":-2867},{"name":"confluence.viewpage.src.quick-create","properties":{"userKey":"${ajs-remote-user-key}","pageID":"${ajs-page-id}","draftID":"${ajs-draft-id}"},"timeDelta":-590},{"name":"confluence.editor.ready.collab.mode.on","properties":{"connectionOrder":"","connectionType":""},"timeDelta":-241}], + "1120": [{"name":"confluence.synchrony.editor.loaded","properties":{"durationMillis":839,"contentId":"${ajs-content-id}"},"timeDelta":-4563},{"name":"browser.metrics.navigation","properties":{"apdex":"0.5","firstPaint":"2222","isInitial":"true","journeyId":"a7c0ccb4-dcf5-46b1-b640-5dda29da5764","key":"confluence.page.create.collaborative.view","navigationType":"0","readyForUser":"3456","redirectCount":"0","resourceLoadedEnd":"2008","resourceLoadedStart":313.95000009797513,"threshold":"1000","unloadEventStart":"292","unloadEventEnd":"292","fetchStart":"1","domainLookupStart":"1","domainLookupEnd":"1","connectStart":"1","connectEnd":"1","requestStart":"4","responseStart":"286","responseEnd":"304","domLoading":"296","domInteractive":"2199","domContentLoadedEventStart":"2199","domContentLoadedEventEnd":"2206","domComplete":"3416","loadEventStart":"3416","loadEventEnd":"3417","userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36","serverDuration":"172","requestCorrelationId":"094ec5fbb427a8c7","resourceTiming":"{\"☠\":[\"2,8p,cw,cn,8z,8p,,8p,8p,8p\",\"2,8q,d0,co,90,8q,,8q,8q,8q\",\"2,8q,g3,g2,ch,ch,,91,91,91\",\"3,8q,xx,g5,ch,ch,,91,91,91\",\"3,8q,1js,g6,ch,ch,,91,91,91\",\"3,8q,hg,h9,cl,cl,,90,90,90\",\"3,8q,ha,gj,cx,8q,,8q,8q,8q\",\"5,1lo,1qn,1q2,1lq,1lo,,1lo,1lo,1lo\",\"5,1lw,1pq,1pp,1ly,1lw,,1lw,1lw,1lw\",\"4,1nn,1re,1rd,1no,1nn,,1nn,1nn,1nn\",\"4,1no,1t8,1t5,1pn,1no,,1no,1no,1no\",\"5,1qm,1u9,1u8,1qo,1qm,,1qm,1qm,1qm\",\"5,1qr,1ud,1uc,1qt,1qr,,1qr,1qr,1qr\",\"5,1qt,1us,1uq,1qz,1qt,,1qt,1qt,1qt\",\"3,1r0,1ut,1us,1r7,1r0,,1r0,1r0,1r0\",\"5,1r5,1v6,1v6,1re,1r5,,1r5,1r5,1r5\",\"5,1rk,1xw,1xw,1ua,1rk,,1rk,1rk,1rk\",\"5,1t5,1wt,1wr,1t8,1t5,,1t5,1t5,1t5\",\"5,202,243,242,203,202,,202,202,202\",\"5,205,23s,23r,208,205,,205,205,205\",\"5,20a,23w,23v,20c,20a,,20a,20a,20a\",\"5,24r,2bx,28g,24t,24r,,24r,24r,24r\",\"5,24r,2ib,2bc,272,24r,,24r,24r,24r\",\"5,26q,2b1,2b0,27d,26q,,26q,26q,26q\",\"5,270,2b2,2b1,27i,270,,270,270,270\",\"5,278,2bp,2bo,27t,278,,278,278,278\",\"5,279,2bn,2bn,284,279,,279,279,279\",\"5,27l,280\",\"2,2br,2fe,2fb,2bs,2br,,2br,2br,2br\",\"3,2br,2mv,2mu,2j5,2br,,2br,2br,2br\",\"5,2jk,2ne,2nb,2jn,2jk,,2jk,2jk,2jk\"]}","mark.@grammarly-extension:checkScriptInitStart":"[2822]","mark.@grammarly-extension:checkScriptInitEnd":"[2823]","userTimingRaw":"{\"marks\":{\"@grammarly-extension:checkScriptInitStart\":[2822],\"@grammarly-extension:checkScriptInitEnd\":[2823]},\"measures\":{}}","experiments":"[]"},"timeDelta":-4550},{"name":"confluence.synchrony.user.in.session","properties":{"numOtherUsers":1,"draftId":"38904870","contentId":"38904870"},"timeDelta":-3417},{"name":"browser.metrics.navigation","properties":{"apdex":"0.5","isInitial":"false","journeyId":"a7c0ccb4-dcf5-46b1-b640-5dda29da5764","key":"confluence.page.create.collaborative.view.connected","readyForUser":"1138","threshold":"1000","userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36","resourceTiming":"{\"☠\":[\"5,ea,ec\"]}","userTimingRaw":"{\"marks\":{},\"measures\":{}}","experiments":"[]"},"timeDelta":-3415}], + "1180": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","atl.confluence.plugins.pagetree-desktop","main","viewcontent","atl.general","page","atl.comments"],"xr":[]}, + "1280": {"r":[],"c":["request-access-plugin"],"xc":["_super","atl.confluence.plugins.pagetree-desktop","main","viewcontent","atl.general","page","atl.comments","browser-metrics-plugin.contrib"],"xr":[]}, + "1300": [{"name":"confluence.viewpage.src.empty","properties":{"userKey":"${ajs-remote-user-key}","pageID":"${ajs-page-id}"},"timeDelta":-502},{"name":"confluence.page.view","properties":{"pageID":"${ajs-page-id}"},"timeDelta":-495},{"name":"browser.metrics.navigation","properties":{"apdex":"1","firstPaint":"861","isInitial":"true","journeyId":"a7c0ccb4-dcf5-46b1-b640-5dda29da5764","key":"confluence.page.view","navigationType":"0","readyForUser":"933","redirectCount":"0","resourceLoadedEnd":"718","resourceLoadedStart":303.38499997742474,"threshold":"1000","unloadEventStart":"279","unloadEventEnd":"279","fetchStart":"5","domainLookupStart":"5","domainLookupEnd":"5","connectStart":"5","connectEnd":"5","requestStart":"14","responseStart":"274","responseEnd":"288","domLoading":"282","domInteractive":"842","domContentLoadedEventStart":"842","domContentLoadedEventEnd":"851","domComplete":"1246","loadEventStart":"1246","loadEventEnd":"1248","userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36","serverDuration":"145","requestCorrelationId":"20f982530b81615b","resourceTiming":"{\"☠\":[\"2,8f,fz,cc,8o,8f,,8f,8f,8f\",\"2,8f,g9,cl,8p,8f,,8f,8f,8f\",\"3,8f,jy,cb,8p,8f,,8f,8f,8f\",\"3,8f,jo,cg,8p,8f,,8f,8f,8f\",\"5,lw,pt,pt,ly,lw,,lw,lw,lw\",\"5,m1,pp,po,m3,m1,,m1,m1,m1\"]}","userTimingRaw":"{\"marks\":{},\"measures\":{}}","experiments":"[]"},"timeDelta":-160}], + "1310": {"r":[],"c":["editor-v4","editor","macro-browser","fullpage-editor"],"xc":["_super","atl.confluence.plugins.pagetree-desktop","main","viewcontent","atl.general","page","atl.comments","browser-metrics-plugin.contrib","request-access-plugin"],"xr":[]}, + "1430": [{"name":"view.edit.transition.edit.button.clicked","properties":{"method":"by-other"},"timeDelta":-3837},{"name":"confluence.synchrony.client.content.reconciliation.blank-content","properties":{"contentId":"${ajs-content-id}"},"timeDelta":-3697},{"name":"confluence.editor.ready.collab.mode.on","properties":{"connectionOrder":"secondary","connectionType":"synchrony-proxy"},"timeDelta":-3369},{"name":"quick-edit-success","timeDelta":-3352},{"name":"confluence.synchrony.editor.loaded","properties":{"durationMillis":17,"contentId":"${ajs-content-id}"},"timeDelta":-3334},{"name":"browser.metrics.navigation","properties":{"apdex":"1","isInitial":"false","journeyId":"a7c0ccb4-dcf5-46b1-b640-5dda29da5764","key":"confluence.page.edit.collaborative.quick-view","readyForUser":"505","threshold":"1000","userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36","resourceTiming":"{\"☠\":[\"5,5s,9l,9k,5u,5s,,5s,5s,5s\"]}","userTimingRaw":"{\"marks\":{},\"measures\":{}}","experiments":"[]"},"timeDelta":-3321},{"name":"confluence.synchrony.user.in.session","properties":{"numOtherUsers":1,"draftId":"38904871","contentId":"38904870"},"timeDelta":-2606},{"name":"browser.metrics.navigation","properties":{"apdex":"1","isInitial":"false","journeyId":"a7c0ccb4-dcf5-46b1-b640-5dda29da5764","key":"confluence.page.edit.collaborative.quick-view.connected","readyForUser":"723","threshold":"1000","userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36","resourceTiming":"{\"☠\":[\"5,3k,7n,7m,3m,3k,,3k,3k,3k\",\"5,44,7r,7q,47,44,,44,44,44\"]}","mark.@grammarly-extension:gButtonShow":"[67]","userTimingRaw":"{\"marks\":{\"@grammarly-extension:gButtonShow\":[67]},\"measures\":{}}","experiments":"[]"},"timeDelta":-2603}], + "1450": [{"name":"confluence.editor.transition.firstkeydown","properties":{"delay":20017},"timeDelta":-3472}], + "1500": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","atl.confluence.plugins.pagetree-desktop","main","viewcontent","atl.general","page","atl.comments"],"xr":[]}, + "1600": {"r":[],"c":["request-access-plugin"],"xc":["_super","atl.confluence.plugins.pagetree-desktop","main","viewcontent","atl.general","page","atl.comments","browser-metrics-plugin.contrib"],"xr":[]}, + "1620": [{"name":"confluence.viewpage.src.empty","properties":{"userKey":"${ajs-remote-user-key}","pageID":"${ajs-page-id}"},"timeDelta":-503},{"name":"confluence.page.view","properties":{"pageID":"${ajs-page-id}"},"timeDelta":-497},{"name":"browser.metrics.navigation","properties":{"apdex":"1","firstPaint":"906","isInitial":"true","journeyId":"a7c0ccb4-dcf5-46b1-b640-5dda29da5764","key":"confluence.page.view","navigationType":"0","readyForUser":"978","redirectCount":"0","resourceLoadedEnd":"762","resourceLoadedStart":237.39999998360872,"threshold":"1000","unloadEventStart":"212","unloadEventEnd":"212","fetchStart":"7","domainLookupStart":"7","domainLookupEnd":"7","connectStart":"7","connectEnd":"7","requestStart":"14","responseStart":"208","responseEnd":"222","domLoading":"216","domInteractive":"889","domContentLoadedEventStart":"889","domContentLoadedEventEnd":"895","domComplete":"1277","loadEventStart":"1277","loadEventEnd":"1279","userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36","serverDuration":"79","requestCorrelationId":"a0c10edb3d00e84c","resourceTiming":"{\"☠\":[\"2,6l,az,am,6v,6l,,6l,6l,6l\",\"2,6l,b3,az,6v,6l,,6l,6l,6l\",\"3,6l,l6,ak,6w,6l,,6l,6l,6l\",\"3,6l,em,ai,6w,6l,,6l,6l,6l\",\"5,n4,qv,qv,n6,n4,,n4,n4,n4\",\"5,nb,qz,qy,nd,nb,,nb,nb,nb\"]}","userTimingRaw":"{\"marks\":{},\"measures\":{}}","experiments":"[]"},"timeDelta":-176}], + "1630": {"r":[],"c":["editor-v4","editor","macro-browser","fullpage-editor"],"xc":["_super","atl.confluence.plugins.pagetree-desktop","main","viewcontent","atl.general","page","atl.comments","browser-metrics-plugin.contrib","request-access-plugin"],"xr":[]} + }, + "comment_page": { + "1740": [{"name":"confluence.page.reading","properties":{"pageID":"${page_id}"},"timeDelta":-880},{"name":"confluence.page.comment.create","properties":{"pageID":"${page_id}"},"timeDelta":-376},{"name":"confluence.editor.action","properties":{"keys":40,"pageID":"${page_id}","editorVersion":"0.74.1"},"timeDelta":-190}] + }, + "view_attachment": { + "1810": {"r":[],"c":["request-access-plugin"],"xc":["_super","viewattachments","main","atl.general","page","atl.confluence.plugins.pagetree-desktop"],"xr":["confluence.web.resources:attachments","com.atlassian.auiplugin:split_aui.splitchunk.036a05e5ff","com.atlassian.auiplugin:split_aui.component.nav","com.atlassian.confluence.plugins.confluence-space-ia:soy-resources","com.atlassian.auiplugin:split_aui.splitchunk.vendors--fc45e4dda1","com.atlassian.auiplugin:split_jquery.ui.sortable","com.atlassian.confluence.plugins.confluence-space-ia:spacesidebar","confluence.web.resources:pagination-styles"]}, + "1830": [{"name":"confluence.viewpage.src.empty","properties":{"userKey":"${ajs-remote-user-key}","pageID":"${page_id}"},"timeDelta":-505}], + "1840": {"r":[],"c":["editor-v4","editor","macro-browser","fullpage-editor"],"xc":["_super","viewattachments","main","atl.general","page","atl.confluence.plugins.pagetree-desktop","request-access-plugin"],"xr":["confluence.web.resources:attachments","com.atlassian.auiplugin:split_aui.splitchunk.036a05e5ff","com.atlassian.auiplugin:split_aui.component.nav","com.atlassian.confluence.plugins.confluence-space-ia:soy-resources","com.atlassian.auiplugin:split_aui.splitchunk.vendors--fc45e4dda1","com.atlassian.auiplugin:split_jquery.ui.sortable","com.atlassian.confluence.plugins.confluence-space-ia:spacesidebar","confluence.web.resources:pagination-styles"]}, + "1890": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","viewattachments","main","atl.general","page","atl.confluence.plugins.pagetree-desktop","request-access-plugin"],"xr":["confluence.web.resources:attachments","com.atlassian.auiplugin:split_aui.splitchunk.036a05e5ff","com.atlassian.auiplugin:split_aui.component.nav","com.atlassian.confluence.plugins.confluence-space-ia:soy-resources","com.atlassian.auiplugin:split_aui.splitchunk.vendors--fc45e4dda1","com.atlassian.auiplugin:split_jquery.ui.sortable","com.atlassian.confluence.plugins.confluence-space-ia:spacesidebar","confluence.web.resources:pagination-styles","com.atlassian.auiplugin:split_aui.component.form.date-select","com.atlassian.auiplugin:split_aui.splitchunk.e8173e0382","com.atlassian.auiplugin:split_aui.component.form.select2","com.atlassian.auiplugin:split_aui.splitchunk.vendors--8cfcf1af69","com.atlassian.auiplugin:split_aui.component.form.file-select","com.atlassian.auiplugin:split_aui.deprecated.pattern.toolbar1","com.atlassian.auiplugin:split_aui.splitchunk.vendors--85718a7eef","com.atlassian.auiplugin:split_aui.splitchunk.vendors--7c76061134","com.atlassian.confluence.plugins.confluence-ui-components:space-page-picker","com.atlassian.confluence.plugins.confluence-ui-components:user-group-select2","com.atlassian.confluence.plugins.confluence-ui-components:cql","com.atlassian.confluence.plugins.confluence-create-content-plugin:user-select2","confluence.web.components:editor-notifications","confluence.web.resources:draft-changes-css","com.atlassian.confluence.plugins.confluence-macro-browser:macro-browser-css","confluence.web.resources:macro-browser-sprites","com.atlassian.confluence.editor:page-editor-css","com.atlassian.confluence.editor:unpublished-changes","com.atlassian.confluence.plugins.reliablesave:reliable-save-conf-frontend","com.atlassian.confluence.editor:property-panel-image-link-macro-conf-frontend","com.atlassian.confluence.image.effects.ImageEffectsPlugin:propertiespanel","com.atlassian.plugins.editor:atlassian-rte-css","com.atlassian.confluence.plugins.confluence-collaborative-editor-plugin:confluence-collaborative-editor-plugin-resources","com.atlassian.confluence.plugins.confluence-create-content-plugin:create-from-template-resources","com.atlassian.confluence.plugins.confluence-fixed-headers:confluence-fixed-headers-editor-resources","com.atlassian.confluence.plugins.confluence-hipchat-emoticons-plugin:hipchat-emoticons-conf-frontend","com.atlassian.confluence.plugins.confluence-link-browser:linkbrowser-css-resources","com.atlassian.confluence.plugins.confluence-mentions-plugin:smart-mentions-editor-resources","com.atlassian.confluence.plugins.confluence-page-layout:pagelayout-frontend","com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-dialog-resources","com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-editor-toolbar-view-resources","com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-editor-resources","com.atlassian.confluence.plugins.confluence-templates:template-editor-variables-resources","com.atlassian.confluence.plugins.confluence-view-file-macro:view-file-macro-editor-resources","com.atlassian.confluence.plugins.drag-and-drop:drag-and-drop-overlay","com.atlassian.confluence.plugins.gadgets:css","com.atlassian.confluence.plugins.share-page:plus-icon-css","com.atlassian.integration.jira.jira-integration-plugin:fields","com.atlassian.integration.jira.jira-integration-plugin:jira-create-issue-form","confluence.extra.jira:dialogsJs","com.atlassian.auiplugin:split_aui.splitchunk.vendors--ec56cc9135","com.atlassian.auiplugin:split_aui.component.form-validation","com.atlassian.auiplugin:split_aui.splitchunk.vendors--825acd7236","com.atlassian.auiplugin:split_jquery.ui.droppable","com.atlassian.auiplugin:split_jquery.ui.resizable","com.atlassian.auiplugin:split_jquery.ui.selectable","com.atlassian.confluence.editor:analytics","com.atlassian.confluence.editor:attachments-insert-utils-resources","com.atlassian.confluence.editor:editor-internationalisation","confluence.web.resources:dictionary","confluence.web.resources:macro-js-overrides","com.atlassian.confluence.plugins.confluence-ui-components:common","com.atlassian.confluence.plugins.confluence-ui-components:space-picker","confluence.web.resources:date-picker","com.atlassian.confluence.plugins.confluence-ui-components:page-picker","com.atlassian.confluence.plugins.confluence-ui-components:label-picker","com.atlassian.confluence.plugins.confluence-ui-components:include-exclude-picker","com.atlassian.confluence.plugins.confluence-macro-browser:macro-browser-js","com.atlassian.confluence.plugins.confluence-editor-v4:editor-resources-v4","com.atlassian.confluence.editor:bookmark-manager-conf-frontend","com.atlassian.confluence.editor:collaborative-helper","confluence.web.resources:legacy-editor-global-AVOID-IF-POSSIBLE","confluence.web.resources:draft-changes-js","com.atlassian.confluence.editor:page-editor-soy","com.atlassian.confluence.plugins.drag-and-drop:files-upload-analytics","com.atlassian.confluence.editor:panel-components","com.atlassian.confluence.editor:page-editor-js","com.atlassian.confluence.editor:editor-v3-v4-shared-resources","com.atlassian.confluence.editor:editor-resources-v4","com.atlassian.confluence.editor:editor-support-util","com.atlassian.confluence.editor:page-editor-quit-dialog","com.atlassian.confluence.plugins.confluence-image-attributes:soy-resources","com.atlassian.confluence.plugins.confluence-image-attributes:image-attributes","com.atlassian.confluence.ext.newcode-macro-plugin:code-macro-editor","com.atlassian.confluence.extra.officeconnector:macro-browser-smart-fields","com.atlassian.confluence.keyboardshortcuts:confluence-tinymce-keyboard-shortcuts","com.atlassian.plugins.browser.metrics.browser-metrics-plugin:api","com.atlassian.confluence.plugins.confluence-browser-metrics:editor","com.atlassian.confluence.plugins.confluence-create-content-plugin:create-from-template-macro-browser-resources","com.atlassian.confluence.plugins.confluence-create-content-plugin:editor-resources","com.atlassian.confluence.plugins.confluence-fixed-headers:utils","com.atlassian.confluence.plugins.confluence-frontend:split_jquery-selection-plugin","com.atlassian.confluence.plugins.confluence-inline-tasks:confluence-inlineTasks-utils","com.atlassian.confluence.plugins.confluence-inline-tasks:datepicker1","com.atlassian.confluence.plugins.confluence-inline-tasks:dateutil","com.atlassian.confluence.plugins.confluence-inline-tasks:date-helper-js-resources","com.atlassian.confluence.plugins.confluence-inline-tasks:editor-autocomplete-date-js","com.atlassian.confluence.plugins.confluence-inline-tasks:space-page-picker-shim","com.atlassian.confluence.plugins.confluence-inline-tasks:inline-tasks-macro-browser","confluence.web.resources:trigger","confluence.web.resources:keyboard","confluence.web.resources:jira-controls","confluence.web.resources:breadcrumbs-jquery","confluence.web.resources:dialog-breadcrumbs","confluence.web.resources:page-location","com.atlassian.confluence.plugins.confluence-link-browser:link-browser-resources","com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-analytics-resources","com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-bar-dialog-resources","com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-utilities-resources","com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-models","com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-editor-timeline-view-resources","com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-editor-view-resources","com.atlassian.confluence.plugins.confluence-templates:template-editor-variables-template-resources","com.atlassian.confluence.plugins.drag-and-drop:image-dialog-client","com.atlassian.confluence.plugins.drag-and-drop:drag-and-drop-tip","com.atlassian.confluence.plugins.drag-and-drop:drag-and-drop-for-editor-common","com.atlassian.confluence.plugins.drag-and-drop:drop-zone-for-image-dialog","com.atlassian.gadgets.embedded:gadget-core-resources","com.atlassian.confluence.plugins.gadgets:macro-browser-for-gadgetsplugin","com.atlassian.confluence.plugins.profile-picture:profile-picture-editor_resources","com.atlassian.confluence.plugins.quickedit:editor-view-resources","com.atlassian.confluence.plugins.share-page:edit-resources","com.atlassian.confluence.plugins.sticky-table-headers:stickytableheaders-resources","confluence.extra.jira:proxy-js","confluence.extra.jira:jqlHelper","confluence.extra.jira:editor-resources-v4-exporter","confluence.extra.jira:jiraAnalytics","confluence.extra.jira:jirachart-macro","confluence.extra.jira:macro-browser-resources","confluence.extra.jira:text-placeholders-jira","confluence.macros.advanced:include_macro","confluence.macros.multimedia:macro-browser-smart-fields"]} + }, + "upload_attachments": { + "1940": {"r":[],"c":["request-access-plugin"],"xc":["_super","atl.confluence.plugins.pagetree-desktop","main","viewattachments","atl.general","page"],"xr":["confluence.web.resources:attachments","com.atlassian.confluence.plugins.confluence-previews:companion-plugin-templates","com.atlassian.auiplugin:split_aui.pattern.help","com.atlassian.confluence.plugins.confluence-previews:companion-plugin-button","com.atlassian.confluence.plugins.confluence-previews:companion-client-wrapper","com.atlassian.confluence.plugins.confluence-previews:mediaviewer-companion","com.atlassian.confluence.plugins.confluence-previews:embedded-edit","com.atlassian.auiplugin:split_aui.splitchunk.036a05e5ff","com.atlassian.auiplugin:split_aui.component.nav","com.atlassian.confluence.plugins.confluence-space-ia:soy-resources","com.atlassian.auiplugin:split_aui.splitchunk.vendors--fc45e4dda1","com.atlassian.auiplugin:split_jquery.ui.sortable","com.atlassian.confluence.plugins.confluence-space-ia:spacesidebar","com.atlassian.confluence.plugins.confluence-previews:confluence-plugin-css","confluence.web.resources:pagination-styles"]}, + "1950": [{"name":"confluence.synchrony.exit.before.connecting","properties":{"afterTimeout":false,"contentId":"${x_editable_g2}"},"timeDelta":-4777},{"name":"confluence.viewpage.src.empty","properties":{"userKey":"${ajs-remote-user-key}","pageID":"${x_editable_g2}"},"timeDelta":-503}], + "1970": {"r":[],"c":["editor-v4","editor","macro-browser","fullpage-editor"],"xc":["_super","atl.confluence.plugins.pagetree-desktop","main","viewattachments","atl.general","page","request-access-plugin"],"xr":["confluence.web.resources:attachments","com.atlassian.confluence.plugins.confluence-previews:companion-plugin-templates","com.atlassian.auiplugin:split_aui.pattern.help","com.atlassian.confluence.plugins.confluence-previews:companion-plugin-button","com.atlassian.confluence.plugins.confluence-previews:companion-client-wrapper","com.atlassian.confluence.plugins.confluence-previews:mediaviewer-companion","com.atlassian.confluence.plugins.confluence-previews:embedded-edit","com.atlassian.auiplugin:split_aui.splitchunk.036a05e5ff","com.atlassian.auiplugin:split_aui.component.nav","com.atlassian.confluence.plugins.confluence-space-ia:soy-resources","com.atlassian.auiplugin:split_aui.splitchunk.vendors--fc45e4dda1","com.atlassian.auiplugin:split_jquery.ui.sortable","com.atlassian.confluence.plugins.confluence-space-ia:spacesidebar","com.atlassian.confluence.plugins.confluence-previews:confluence-plugin-css","confluence.web.resources:pagination-styles"]}, + "1990": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","atl.confluence.plugins.pagetree-desktop","main","viewattachments","atl.general","page","request-access-plugin"],"xr":["confluence.web.resources:attachments","com.atlassian.confluence.plugins.confluence-previews:companion-plugin-templates","com.atlassian.auiplugin:split_aui.pattern.help","com.atlassian.confluence.plugins.confluence-previews:companion-plugin-button","com.atlassian.confluence.plugins.confluence-previews:companion-client-wrapper","com.atlassian.confluence.plugins.confluence-previews:mediaviewer-companion","com.atlassian.confluence.plugins.confluence-previews:embedded-edit","com.atlassian.auiplugin:split_aui.splitchunk.036a05e5ff","com.atlassian.auiplugin:split_aui.component.nav","com.atlassian.confluence.plugins.confluence-space-ia:soy-resources","com.atlassian.auiplugin:split_aui.splitchunk.vendors--fc45e4dda1","com.atlassian.auiplugin:split_jquery.ui.sortable","com.atlassian.confluence.plugins.confluence-space-ia:spacesidebar","com.atlassian.confluence.plugins.confluence-previews:confluence-plugin-css","confluence.web.resources:pagination-styles","com.atlassian.auiplugin:split_aui.component.form.date-select","com.atlassian.auiplugin:split_aui.splitchunk.e8173e0382","com.atlassian.auiplugin:split_aui.component.form.select2","com.atlassian.auiplugin:split_aui.splitchunk.vendors--8cfcf1af69","com.atlassian.auiplugin:split_aui.component.form.file-select","com.atlassian.auiplugin:split_aui.deprecated.pattern.toolbar1","com.atlassian.auiplugin:split_aui.splitchunk.vendors--85718a7eef","com.atlassian.auiplugin:split_aui.splitchunk.vendors--7c76061134","com.atlassian.confluence.plugins.confluence-ui-components:space-page-picker","com.atlassian.confluence.plugins.confluence-ui-components:user-group-select2","com.atlassian.confluence.plugins.confluence-ui-components:cql","com.atlassian.confluence.plugins.confluence-create-content-plugin:user-select2","confluence.web.components:editor-notifications","confluence.web.resources:draft-changes-css","com.atlassian.confluence.plugins.confluence-macro-browser:macro-browser-css","confluence.web.resources:macro-browser-sprites","com.atlassian.confluence.editor:page-editor-css","com.atlassian.confluence.editor:unpublished-changes","com.atlassian.confluence.plugins.reliablesave:reliable-save-conf-frontend","com.atlassian.confluence.editor:property-panel-image-link-macro-conf-frontend","com.atlassian.confluence.image.effects.ImageEffectsPlugin:propertiespanel","com.atlassian.plugins.editor:atlassian-rte-css","com.atlassian.confluence.plugins.confluence-collaborative-editor-plugin:confluence-collaborative-editor-plugin-resources","com.atlassian.confluence.plugins.confluence-create-content-plugin:create-from-template-resources","com.atlassian.confluence.plugins.confluence-fixed-headers:confluence-fixed-headers-editor-resources","com.atlassian.confluence.plugins.confluence-hipchat-emoticons-plugin:hipchat-emoticons-conf-frontend","com.atlassian.confluence.plugins.confluence-link-browser:linkbrowser-css-resources","com.atlassian.confluence.plugins.confluence-mentions-plugin:smart-mentions-editor-resources","com.atlassian.confluence.plugins.confluence-page-layout:pagelayout-frontend","com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-dialog-resources","com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-editor-toolbar-view-resources","com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-editor-resources","com.atlassian.confluence.plugins.confluence-templates:template-editor-variables-resources","com.atlassian.confluence.plugins.confluence-view-file-macro:view-file-macro-editor-resources","com.atlassian.confluence.plugins.drag-and-drop:drag-and-drop-overlay","com.atlassian.confluence.plugins.gadgets:css","com.atlassian.confluence.plugins.share-page:plus-icon-css","com.atlassian.integration.jira.jira-integration-plugin:fields","com.atlassian.integration.jira.jira-integration-plugin:jira-create-issue-form","confluence.extra.jira:dialogsJs","com.atlassian.auiplugin:split_aui.splitchunk.vendors--ec56cc9135","com.atlassian.auiplugin:split_aui.component.form-validation","com.atlassian.auiplugin:split_aui.splitchunk.vendors--825acd7236","com.atlassian.auiplugin:split_jquery.ui.droppable","com.atlassian.auiplugin:split_jquery.ui.resizable","com.atlassian.auiplugin:split_jquery.ui.selectable","com.atlassian.confluence.editor:analytics","com.atlassian.confluence.editor:attachments-insert-utils-resources","com.atlassian.confluence.editor:editor-internationalisation","confluence.web.resources:dictionary","confluence.web.resources:macro-js-overrides","com.atlassian.confluence.plugins.confluence-ui-components:common","com.atlassian.confluence.plugins.confluence-ui-components:space-picker","confluence.web.resources:date-picker","com.atlassian.confluence.plugins.confluence-ui-components:page-picker","com.atlassian.confluence.plugins.confluence-ui-components:label-picker","com.atlassian.confluence.plugins.confluence-ui-components:include-exclude-picker","com.atlassian.confluence.plugins.confluence-macro-browser:macro-browser-js","com.atlassian.confluence.plugins.confluence-editor-v4:editor-resources-v4","com.atlassian.confluence.editor:bookmark-manager-conf-frontend","com.atlassian.confluence.editor:collaborative-helper","confluence.web.resources:legacy-editor-global-AVOID-IF-POSSIBLE","confluence.web.resources:draft-changes-js","com.atlassian.confluence.editor:page-editor-soy","com.atlassian.confluence.plugins.drag-and-drop:files-upload-analytics","com.atlassian.confluence.editor:panel-components","com.atlassian.confluence.editor:page-editor-js","com.atlassian.confluence.editor:editor-v3-v4-shared-resources","com.atlassian.confluence.editor:editor-resources-v4","com.atlassian.confluence.editor:editor-support-util","com.atlassian.confluence.editor:page-editor-quit-dialog","com.atlassian.confluence.plugins.confluence-image-attributes:soy-resources","com.atlassian.confluence.plugins.confluence-image-attributes:image-attributes","com.atlassian.confluence.ext.newcode-macro-plugin:code-macro-editor","com.atlassian.confluence.extra.officeconnector:macro-browser-smart-fields","com.atlassian.confluence.keyboardshortcuts:confluence-tinymce-keyboard-shortcuts","com.atlassian.plugins.browser.metrics.browser-metrics-plugin:api","com.atlassian.confluence.plugins.confluence-browser-metrics:editor","com.atlassian.confluence.plugins.confluence-create-content-plugin:create-from-template-macro-browser-resources","com.atlassian.confluence.plugins.confluence-create-content-plugin:editor-resources","com.atlassian.confluence.plugins.confluence-fixed-headers:utils","com.atlassian.confluence.plugins.confluence-frontend:split_jquery-selection-plugin","com.atlassian.confluence.plugins.confluence-inline-tasks:confluence-inlineTasks-utils","com.atlassian.confluence.plugins.confluence-inline-tasks:datepicker1","com.atlassian.confluence.plugins.confluence-inline-tasks:dateutil","com.atlassian.confluence.plugins.confluence-inline-tasks:date-helper-js-resources","com.atlassian.confluence.plugins.confluence-inline-tasks:editor-autocomplete-date-js","com.atlassian.confluence.plugins.confluence-inline-tasks:space-page-picker-shim","com.atlassian.confluence.plugins.confluence-inline-tasks:inline-tasks-macro-browser","confluence.web.resources:trigger","confluence.web.resources:keyboard","confluence.web.resources:jira-controls","confluence.web.resources:breadcrumbs-jquery","confluence.web.resources:dialog-breadcrumbs","confluence.web.resources:page-location","com.atlassian.confluence.plugins.confluence-link-browser:link-browser-resources","com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-analytics-resources","com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-bar-dialog-resources","com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-utilities-resources","com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-models","com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-editor-timeline-view-resources","com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-editor-view-resources","com.atlassian.confluence.plugins.confluence-templates:template-editor-variables-template-resources","com.atlassian.confluence.plugins.drag-and-drop:image-dialog-client","com.atlassian.confluence.plugins.drag-and-drop:drag-and-drop-tip","com.atlassian.confluence.plugins.drag-and-drop:drag-and-drop-for-editor-common","com.atlassian.confluence.plugins.drag-and-drop:drop-zone-for-image-dialog","com.atlassian.gadgets.embedded:gadget-core-resources","com.atlassian.confluence.plugins.gadgets:macro-browser-for-gadgetsplugin","com.atlassian.confluence.plugins.profile-picture:profile-picture-editor_resources","com.atlassian.confluence.plugins.quickedit:editor-view-resources","com.atlassian.confluence.plugins.share-page:edit-resources","com.atlassian.confluence.plugins.sticky-table-headers:stickytableheaders-resources","confluence.extra.jira:proxy-js","confluence.extra.jira:jqlHelper","confluence.extra.jira:editor-resources-v4-exporter","confluence.extra.jira:jiraAnalytics","confluence.extra.jira:jirachart-macro","confluence.extra.jira:macro-browser-resources","confluence.extra.jira:text-placeholders-jira","confluence.macros.advanced:include_macro","confluence.macros.multimedia:macro-browser-smart-fields"]} } } \ No newline at end of file diff --git a/app/locustio/jira/http_actions.py b/app/locustio/jira/http_actions.py index 371640003..c775a7a04 100644 --- a/app/locustio/jira/http_actions.py +++ b/app/locustio/jira/http_actions.py @@ -26,31 +26,59 @@ def login_and_view_dashboard(locust): body['os_username'] = user[0] body['os_password'] = user[1] - locust.post('/login.jsp', body, TEXT_HEADERS, catch_response=True) + # 100 /login.jsp + locust.post('/login.jsp', body, + TEXT_HEADERS, + catch_response=True) + r = locust.get('/', catch_response=True) if not r.content: raise Exception('Please check server hostname in jira.yml file') content = r.content.decode('utf-8') - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("110"), - headers=RESOURCE_HEADERS, catch_response=True) + + # 110 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("110"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 115 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("115"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 120 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("120"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 125 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("125"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 130 /plugins/servlet/gadgets/dashboard-diagnostics locust.post("/plugins/servlet/gadgets/dashboard-diagnostics", {"uri": f"{locust.client.base_url.lower()}/secure/Dashboard.jspa"}, - TEXT_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("120"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("125"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("130"), - headers=RESOURCE_HEADERS, catch_response=True) + TEXT_HEADERS, + catch_response=True) + # 135 /rest/activity-stream/1.0/preferences locust.get(f'/rest/activity-stream/1.0/preferences?_={timestamp_int()}', catch_response=True) + + # 140 /rest/gadget/1.0/issueTable/jql locust.get(f'/rest/gadget/1.0/issueTable/jql?num=10&tableContext=jira.table.cols.dashboard' f'&addDefault=true&enableSorting=true&paging=true&showActions=true' f'&jql=assignee+%3D+currentUser()+AND' f'+resolution+%3D+unresolved+ORDER+BY+priority+DESC%2C+created+ASC' f'&sortBy=&startIndex=0&_={timestamp_int()}', catch_response=True) - locust.get(f'/plugins/servlet/streams?maxResults=5&relativeLinks=true&_={timestamp_int()}', - catch_response=True) + + # 145 /plugins/servlet/streams + locust.get(f'/plugins/servlet/streams?maxResults=5&relativeLinks=true&_={timestamp_int()}', catch_response=True) + # Assertions token = fetch_by_re(params.atl_token_pattern, content) if not (f'title="loggedInUser" value="{user[0]}">' in content): @@ -70,23 +98,62 @@ def view_issue(locust): issue_key = random.choice(jira_dataset['issues'])[0] project_key = random.choice(jira_dataset['issues'])[2] + # 400 /browse r = locust.get(f'/browse/{issue_key}', catch_response=True) + content = r.content.decode('utf-8') issue_id = fetch_by_re(params.issue_id_pattern, content) project_avatar_id = fetch_by_re(params.project_avatar_id_pattern, content) edit_allowed = fetch_by_re(params.edit_allow_pattern, content, group_no=0) + + # 405 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("405"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 410 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("410"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 415 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("415"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 420 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("420"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 425 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("425"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 430 /secure/projectavatar locust.get(f'/secure/projectavatar?avatarId={project_avatar_id}', catch_response=True) + # Assertions - if not(f'<meta name="ajs-issue-key" content="{issue_key}">' in content): + if not (f'<meta name="ajs-issue-key" content="{issue_key}">' in content): logger.error(f'Issue {issue_key} not found: {content}') assert f'<meta name="ajs-issue-key" content="{issue_key}">' in content, 'Issue not found' logger.locust_info(f"{params.action_name}: Issue {issue_key} is opened successfully") - logger.locust_info(f'{params.action_name}: Issue key - {issue_key}, issue_id - {issue_id}') + + # 435 /secure/AjaxIssueEditAction!default.jspa if edit_allowed: url = f'/secure/AjaxIssueEditAction!default.jspa?decorator=none&issueId={issue_id}&_={timestamp_int()}' locust.get(url, catch_response=True) - locust.client.put(f'/rest/projects/1.0/project/{project_key}/lastVisited', params.browse_project_payload, + + # 440 /rest/projects/1.0/project/<project_key>/lastVisited + locust.client.put(f'/rest/projects/1.0/project/{project_key}/lastVisited', + params.browse_project_payload, catch_response=True) @@ -98,8 +165,10 @@ def create_issue(locust): @jira_measure('locust_create_issue:open_quick_create') def create_issue_open_quick_create(): raise_if_login_failed(locust) - r = locust.post('/secure/QuickCreateIssue!default.jspa?decorator=none', - ADMIN_HEADERS, catch_response=True) + + # 200 /secure/QuickCreateIssue!default.jspa?decorator=none + r = locust.post('/secure/QuickCreateIssue!default.jspa?decorator=none', ADMIN_HEADERS, catch_response=True) + content = r.content.decode('utf-8') atl_token = fetch_by_re(params.atl_token_pattern, content) form_token = fetch_by_re(params.form_token_pattern, content) @@ -120,9 +189,21 @@ def create_issue_open_quick_create(): if not ('"id":"project","label":"Project"' in content): logger.error(f'{params.err_message_create_issue}: {content}') assert '"id":"project","label":"Project"' in content, params.err_message_create_issue - locust.post('/rest/quickedit/1.0/userpreferences/create', json=params.user_preferences_payload, - headers=ADMIN_HEADERS, catch_response=True) + + # 205 /rest/quickedit/1.0/userpreferences/create + locust.post('/rest/quickedit/1.0/userpreferences/create', + json=params.user_preferences_payload, + headers=ADMIN_HEADERS, + catch_response=True) + + # 210 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("210"), + headers=RESOURCE_HEADERS, + catch_response=True) + locust.session_data_storage['issue_body_params_dict'] = issue_body_params_dict + create_issue_open_quick_create() @jira_measure('locust_create_issue:fill_and_submit_issue_form') @@ -131,14 +212,25 @@ def create_issue_submit_form(): issue_body = params.prepare_issue_body(locust.session_data_storage['issue_body_params_dict'], user=locust.session_data_storage["username"]) - r = locust.post('/secure/QuickCreateIssue.jspa?decorator=none', params=issue_body, - headers=ADMIN_HEADERS, catch_response=True) + # 215 /secure/QuickCreateIssue.jspa?decorator=none + r = locust.post('/secure/QuickCreateIssue.jspa?decorator=none', + params=issue_body, + headers=ADMIN_HEADERS, + catch_response=True) + + # 220 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("220"), + headers=RESOURCE_HEADERS, + catch_response=True) + content = r.content.decode('utf-8') if '"id":"project","label":"Project"' not in content: logger.error(f'{params.err_message_create_issue}: {content}') assert '"id":"project","label":"Project"' in content, params.err_message_create_issue issue_key = fetch_by_re(params.create_issue_key_pattern, content) logger.locust_info(f"{params.action_name}: Issue {issue_key} was successfully created") + create_issue_submit_form() @@ -148,49 +240,96 @@ def search_jql(locust): params = SearchJql() jql = random.choice(jira_dataset['jqls'])[0] - r = locust.get(f'/issues/?jql={jql}', catch_response=True) - content = r.content.decode('utf-8') - if not (locust.session_data_storage["token"] in content): - logger.error(f'Can not search by {jql}: {content}') - assert locust.session_data_storage["token"] in content, 'Can not search by jql' + # 300 /issues + locust.get(f'/issues/?jql={jql}', catch_response=True) + + # 305 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("305"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 310 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("310"), + headers=RESOURCE_HEADERS, + catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("305"), - headers=RESOURCE_HEADERS, catch_response=True) + # 315 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("315"), + headers=RESOURCE_HEADERS, + catch_response=True) + # 320 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("320"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 325 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("325"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 330 /rest/api/2/filter/favourite locust.get(f'/rest/api/2/filter/favourite?expand=subscriptions[-5:]&_={timestamp_int()}', catch_response=True) - locust.post('/rest/issueNav/latest/preferredSearchLayout', params={'layoutKey': 'split-view'}, - headers=NO_TOKEN_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("320"), - headers=RESOURCE_HEADERS, catch_response=True) - r = locust.post('/rest/issueNav/1/issueTable', data=params.issue_table_payload, - headers=NO_TOKEN_HEADERS, catch_response=True) + # 335 /rest/issueNav/latest/preferredSearchLayout + locust.post('/rest/issueNav/latest/preferredSearchLayout', + params={'layoutKey': 'split-view'}, + headers=NO_TOKEN_HEADERS, + catch_response=True) + + # 340 /rest/issueNav/1/issueTable + r = locust.post('/rest/issueNav/1/issueTable', + data=params.issue_table_payload, + headers=NO_TOKEN_HEADERS, + catch_response=True) + content = r.content.decode('utf-8') issue_ids = re.findall(params.ids_pattern, content) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("330"), - headers=RESOURCE_HEADERS, catch_response=True) if issue_ids: body = params.prepare_jql_body(issue_ids) - r = locust.post('/rest/issueNav/1/issueTable/stable', data=body, - headers=NO_TOKEN_HEADERS, catch_response=True) + + # 345 /rest/issueNav/1/issueTable/stable + r = locust.post('/rest/issueNav/1/issueTable/stable', + data=body, + headers=NO_TOKEN_HEADERS, + catch_response=True) + content = r.content.decode('utf-8') issue_key = fetch_by_re(params.issue_key_pattern, content) issue_id = fetch_by_re(params.issue_id_pattern, content) - locust.post('/secure/QueryComponent!Jql.jspa', params={'jql': 'order by created DESC', - 'decorator': None}, headers=TEXT_HEADERS, + + # 350 /secure/QueryComponent!Jql.jspa + locust.post('/secure/QueryComponent!Jql.jspa', + params={'jql': 'order by created DESC', 'decorator': None}, + headers=TEXT_HEADERS, catch_response=True) + + # 355 /rest/orderbycomponent/latest/orderByOptions/primary locust.post('/rest/orderbycomponent/latest/orderByOptions/primary', - json={"jql": "order by created DESC"}, headers=RESOURCE_HEADERS, catch_response=True) + json={"jql": "order by created DESC"}, + headers=RESOURCE_HEADERS, + catch_response=True) + + # 360 /secure/AjaxIssueAction!default.jspa if issue_ids: - r = locust.post('/secure/AjaxIssueAction!default.jspa', params={"decorator": None, - "issueKey": issue_key, - "prefetch": False, - "shouldUpdateCurrentProject": False, - "loadFields": False, - "_": timestamp_int()}, - headers=TEXT_HEADERS, catch_response=True) + r = locust.post('/secure/AjaxIssueAction!default.jspa', + params={"decorator": None, + "issueKey": issue_key, + "prefetch": False, + "shouldUpdateCurrentProject": False, + "loadFields": False, + "_": timestamp_int()}, + headers=TEXT_HEADERS, + catch_response=True) + + # 365 /secure/AjaxIssueEditAction!default.jspa if params.edit_allow_string in r.content.decode('utf-8'): locust.get(f'/secure/AjaxIssueEditAction!default.jspa?' f'decorator=none&issueId={issue_id}&_={timestamp_int()}', catch_response=True) @@ -203,7 +342,9 @@ def view_project_summary(locust): project = random.choice(jira_dataset['projects']) project_key = project[0] + # 500 /projects/<project_key>/summary r = locust.get(f'/projects/{project_key}/summary', catch_response=True) + content = r.content.decode('utf-8') logger.locust_info(f"{params.action_name}. View project {project_key}: {content}") @@ -212,32 +353,43 @@ def view_project_summary(locust): logger.error(f'{params.err_message} {project_key}') assert assert_string in content, params.err_message - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("505"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("510"), - headers=RESOURCE_HEADERS, catch_response=True) + # 505 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("505"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 510 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("510"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 515 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("515"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 520 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("520"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 525 /rest/activity-stream/1.0/preferences locust.get(f'/rest/activity-stream/1.0/preferences?_={timestamp_int()}', catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("520"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.get(f'/plugins/servlet/streams?maxResults=10&relativeLinks=true&streams=key+IS+{project_key}' - f'&providers=thirdparty+dvcs-streams-provider+issues&_={timestamp_int()}', - catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("530"), - headers=RESOURCE_HEADERS, catch_response=True) + + # 530 /projects/<project_key> locust.get(f'/projects/{project_key}?selectedItem=com.atlassian.jira.jira-projects-plugin:' - f'project-activity-summary&decorator=none&contentOnly=true&_={timestamp_int()}', - catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("545"), - headers=RESOURCE_HEADERS, catch_response=True) + f'project-activity-summary&decorator=none&contentOnly=true&_={timestamp_int()}', catch_response=True) + + # 535 /rest/api/2/user/properties/lastViewedVignette locust.client.put(f'/rest/api/2/user/properties/lastViewedVignette?' - f'username={locust.session_data_storage["username"]}', data={"id": "priority"}, - headers=TEXT_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("555"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.get(f'/rest/activity-stream/1.0/preferences?_={timestamp_int()}', catch_response=True) - locust.get(f'/plugins/servlet/streams?maxResults=10&relativeLinks=true&streams=key+IS+{project_key}' - f'&providers=thirdparty+dvcs-streams-provider+issues&_={timestamp_int()}', - catch_response=True) + f'username={locust.session_data_storage["username"]}', + data={"id": "priority"}, + headers=TEXT_HEADERS, + catch_response=True) def edit_issue(locust): @@ -250,9 +402,11 @@ def edit_issue(locust): @jira_measure('locust_edit_issue:open_editor') def edit_issue_open_editor(): raise_if_login_failed(locust) + + # 700 /secure/EditIssue!default.jspa r = locust.get(f'/secure/EditIssue!default.jspa?id={issue_id}', catch_response=True) - content = r.content.decode('utf-8') + content = r.content.decode('utf-8') issue_type = fetch_by_re(params.issue_type_pattern, content) atl_token = fetch_by_re(params.atl_token_pattern, content) priority = fetch_by_re(params.issue_priority_pattern, content, group_no=2) @@ -265,12 +419,31 @@ def edit_issue_open_editor(): params.err_message_issue_not_found logger.locust_info(f"{params.action_name}: Editing issue {issue_key}") - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("705"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("710"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("720"), - headers=RESOURCE_HEADERS, catch_response=True) + # 705 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("705"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 710 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("710"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 715 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("715"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 720 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("720"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 725 /rest/internal/2/user/mention/search locust.get(f'/rest/internal/2/user/mention/search?issueKey={issue_key}' f'&projectKey={project_key}&maxResults=10&_={timestamp_int()}', catch_response=True) @@ -281,32 +454,65 @@ def edit_issue_open_editor(): f'&comment=""&commentLevel=""&atl_token={atl_token}&Update=Update' locust.session_data_storage['edit_issue_body'] = edit_body locust.session_data_storage['atl_token'] = atl_token + edit_issue_open_editor() @jira_measure('locust_edit_issue:save_edit') def edit_issue_save_edit(): raise_if_login_failed(locust) + + # 730 /secure/EditIssue.jspa r = locust.post(f'/secure/EditIssue.jspa?atl_token={locust.session_data_storage["atl_token"]}', params=locust.session_data_storage['edit_issue_body'], - headers=TEXT_HEADERS, catch_response=True) + headers=TEXT_HEADERS, + catch_response=True) + content = r.content.decode('utf-8') if not (f'[{issue_key}]' in content): logger.error(f'Could not save edited page: {content}') assert f'[{issue_key}]' in content, 'Could not save edited page' - locust.get(f'/browse/{issue_key}', catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("740"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("745"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("765"), - headers=RESOURCE_HEADERS, catch_response=True) + # 735 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("735"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 740 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("740"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 745 /rest/bamboo/latest/deploy + locust.get(f'/rest/bamboo/latest/deploy/{project_key}/{issue_key}?_{timestamp_int()}', catch_response=True) + + # 750 /secure/AjaxIssueEditAction!default.jspa locust.get(f'/secure/AjaxIssueEditAction!default.jspa?decorator=none&issueId=' f'{issue_id}&_={timestamp_int()}', catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("775"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.client.put(f'/rest/projects/1.0/project/{project_key}/lastVisited', params.last_visited_body, + + # 755 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("755"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 760 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("760"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 765 /rest/projects/1.0/project/${issue_project_key}/lastVisited + locust.client.put(f'/rest/projects/1.0/project/{project_key}/lastVisited', + params.last_visited_body, catch_response=True) + + # 770 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("770"), + headers=RESOURCE_HEADERS, + catch_response=True) edit_issue_save_edit() @@ -315,30 +521,62 @@ def view_dashboard(locust): raise_if_login_failed(locust) params = ViewDashboard() + # 600 /secure/Dashboard.jspa r = locust.get('/secure/Dashboard.jspa', catch_response=True) + content = r.content.decode('utf-8') if not (f'title="loggedInUser" value="{locust.session_data_storage["username"]}">' in content): logger.error(f'User {locust.session_data_storage["username"]} authentication failed: {content}') assert f'title="loggedInUser" value="{locust.session_data_storage["username"]}">' in content, \ 'User authentication failed' - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("605"), - headers=RESOURCE_HEADERS, catch_response=True) + + # 605 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("605"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 610 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("610"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 615 /rest/gadget/1.0/issueTable/jql + locust.get('/rest/gadget/1.0/issueTable/jql?num=10&tableContext=jira.table.cols.dashboard&addDefault=true' + '&enableSorting=true&paging=true&showActions=true' + '&jql=assignee+%3D+currentUser()+AND+resolution+%3D+unresolved+ORDER+BY+priority+' + 'DESC%2C+created+ASC&sortBy=&startIndex=0&_=1588507042019', + catch_response=True) + + # 620 /plugins/servlet/gadgets/dashboard-diagnostics r = locust.post('/plugins/servlet/gadgets/dashboard-diagnostics', params={'uri': f'{JIRA_SETTINGS.server_url.lower()}//secure/Dashboard.jspa'}, - headers=TEXT_HEADERS, catch_response=True) + headers=TEXT_HEADERS, + catch_response=True) + content = r.content.decode('utf-8') if not ('Dashboard Diagnostics: OK' in content): logger.error(f'view_dashboard dashboard-diagnostics failed: {content}') assert 'Dashboard Diagnostics: OK' in content, 'view_dashboard dashboard-diagnostics failed' - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("620"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.get(f'/rest/activity-stream/1.0/preferences?_={timestamp_int()}', catch_response=True) - locust.get('/rest/gadget/1.0/issueTable/jql?num=10&tableContext=jira.table.cols.dashboard&addDefault=true' - '&enableSorting=true&paging=true&showActions=true' - '&jql=assignee+%3D+currentUser()+AND+resolution+%3D+unresolved+ORDER+BY+priority+' - 'DESC%2C+created+ASC&sortBy=&startIndex=0&_=1588507042019', catch_response=True) - locust.get(f'/plugins/servlet/streams?maxResults=5&relativeLinks=true&_={timestamp_int()}', - catch_response=True) + + # 625 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("625"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 630 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("630"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 635 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("635"), + headers=RESOURCE_HEADERS, + catch_response=True) def add_comment(locust): @@ -351,7 +589,10 @@ def add_comment(locust): @jira_measure('locust_add_comment:open_comment') def add_comment_open_comment(): raise_if_login_failed(locust) + + # 800 /secure/AddComment!default.jspa r = locust.get(f'/secure/AddComment!default.jspa?id={issue_id}', catch_response=True) + content = r.content.decode('utf-8') token = fetch_by_re(params.atl_token_pattern, content) form_token = fetch_by_re(params.form_token_pattern, content) @@ -359,30 +600,94 @@ def add_comment_open_comment(): logger.error(f'Could not open comment in the {issue_key} issue: {content}') assert f'Add Comment: {issue_key}' in content, 'Could not open comment in the issue' - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("805"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("810"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("820"), - headers=RESOURCE_HEADERS, catch_response=True) + # 805 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("805"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 810 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("810"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 815 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("815"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 820 /rest/internal/2/user/mention/search locust.get(f'/rest/internal/2/user/mention/search?issueKey={issue_key}&projectKey={project_key}' f'&maxResults=10&_={timestamp_int()}', catch_response=True) locust.session_data_storage['token'] = token locust.session_data_storage['form_token'] = form_token + + # 825 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("825"), + headers=RESOURCE_HEADERS, + catch_response=True) + add_comment_open_comment() @jira_measure('locust_add_comment:save_comment') def add_comment_save_comment(): raise_if_login_failed(locust) + + # 845 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("845"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 850 /secure/AddComment.jspa r = locust.post(f'/secure/AddComment.jspa?atl_token={locust.session_data_storage["token"]}', params={"id": {issue_id}, "formToken": locust.session_data_storage["form_token"], "dnd-dropzone": None, "comment": generate_random_string(20), "commentLevel": None, "atl_token": locust.session_data_storage["token"], - "Add": "Add"}, headers=TEXT_HEADERS, catch_response=True) + "Add": "Add"}, + headers=TEXT_HEADERS, + catch_response=True) + content = r.content.decode('utf-8') if not (f'<meta name="ajs-issue-key" content="{issue_key}">' in content): logger.error(f'Could not save comment: {content}') assert f'<meta name="ajs-issue-key" content="{issue_key}">' in content, 'Could not save comment' + + # 860 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("860"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 865 /rest/bamboo/latest/deploy/${issue_project_key}/{issue_key} + locust.get(f'/rest/bamboo/latest/deploy/{project_key}/{issue_key}?_={timestamp_int()}', catch_response=True) + + # 870 /secure/AjaxIssueEditAction!default.jspa + locust.get(f'/secure/AjaxIssueEditAction!default.jspa?' + f'decorator=none' + f'&issueId={issue_id}' + f'&_={timestamp_int()}', catch_response=True) + + # 875 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("875"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 880 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("880"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 885 /rest/projects/1.0/project + locust.client.put(f'/rest/projects/1.0/project/{project_key}/lastVisited', + params.browse_project_payload, + catch_response=True) + add_comment_save_comment() @@ -392,65 +697,94 @@ def browse_projects(locust): params = BrowseProjects() page = random.randint(1, jira_dataset['pages']) + + # 900 /secure/BrowseProjects.jspa r = locust.get(f'/secure/BrowseProjects.jspa?selectedCategory=all&selectedProjectType=all&page={page}', catch_response=True) + content = r.content.decode('utf-8') if not ('WRM._unparsedData["com.atlassian.jira.project.browse:projects"]="' in content): logger.error(f'Could not browse projects: {content}') assert 'WRM._unparsedData["com.atlassian.jira.project.browse:projects"]="' in content, 'Could not browse projects' - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("905"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("910"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("920"), - headers=RESOURCE_HEADERS, catch_response=True) + + # 905 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("905"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 910 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("910"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 915 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("915"), + headers=RESOURCE_HEADERS, + catch_response=True) @jira_measure('locust_view_kanban_board') def view_kanban_board(locust): raise_if_login_failed(locust) kanban_board_id = random.choice(jira_dataset["kanban_boards"])[0] - view_board(locust, kanban_board_id) + kanban_board(locust, kanban_board_id) @jira_measure('locust_view_scrum_board') def view_scrum_board(locust): raise_if_login_failed(locust) scrum_board_id = random.choice(jira_dataset["scrum_boards"])[0] - view_board(locust, scrum_board_id) + scrum_board(locust, scrum_board_id) @jira_measure('locust_view_backlog') def view_backlog(locust): raise_if_login_failed(locust) scrum_board_id = random.choice(jira_dataset["scrum_boards"])[0] - view_board(locust, scrum_board_id, view_backlog=True) + backlog_board(locust, scrum_board_id) @jira_measure('locust_browse_boards') def browse_boards(locust): + raise_if_login_failed(locust) params = BrowseBoards() + + # 1300 /secure/ManageRapidViews.jspa locust.get('/secure/ManageRapidViews.jspa', catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("1205"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("1210"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("1215"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("1225"), - headers=RESOURCE_HEADERS, catch_response=True) + + # 1305 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("1305"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1310 /rest/greenhopper/1.0/rapidviews/viewsData locust.get(f'/rest/greenhopper/1.0/rapidviews/viewsData?_{timestamp_int()}', catch_response=True) + # 1315 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("1315"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1320 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("1320"), + headers=RESOURCE_HEADERS, + catch_response=True) + -def view_board(locust, board_id, view_backlog=False): - params = ViewBoard() - if view_backlog: - url = f'/secure/RapidBoard.jspa?rapidView={board_id}&view=planning' - else: - url = f'/secure/RapidBoard.jspa?rapidView={board_id}' +def kanban_board(locust, board_id): + params = ViewBoard(action_name='view_kanban_board') + url = f'/secure/RapidBoard.jspa?rapidView={board_id}' + # 1000 /secure/RapidBoard.jspa r = locust.get(url, catch_response=True) + content = r.content.decode('utf-8') project_key = fetch_by_re(params.project_key_pattern, content) project_id = fetch_by_re(params.project_id_pattern, content) @@ -460,44 +794,262 @@ def view_board(locust, board_id, view_backlog=False): logger.locust_info(f"{params.action_name}: key = {project_key}, id = {project_id}, plan = {project_plan}") assert f'currentViewConfig\"{{\"id\":{board_id}', 'Could not open board' - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("1000"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("1005"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("1010"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("1015"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("1020"), - headers=RESOURCE_HEADERS, catch_response=True) + # 1005 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("1005"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1010 /rest/greenhopper/1.0/xboard/config.json + locust.get(f'/rest/greenhopper/1.0/xboard/config.json?' + f'returnDefaultBoard=true' + f'&_={timestamp_int()}', catch_response=True) + + # 1015 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("1015"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1025 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("1025"), + headers=RESOURCE_HEADERS, + catch_response=True) if project_key: + # 1030 /rest/api/2/project/${x_project_key} locust.get(f'/rest/api/2/project/{project_key}?_={timestamp_int()}', catch_response=True) - locust.get(f'/rest/greenhopper/1.0/xboard/toolSections?mode=work&rapidViewId={board_id}' - f'&selectedProjectKey={project_key}&_={timestamp_int()}', catch_response=True) - locust.get(f'/rest/greenhopper/1.0/xboard/work/allData.json?rapidViewId={board_id}' - f'&selectedProjectKey={project_key}&_={timestamp_int()}', catch_response=True) - if view_backlog: - locust.get(f'/rest/inline-create/1.0/context/bootstrap?query=' - f'project%20%3D%20%22{project_key}%22%20ORDER%20BY%20Rank%20ASC&&_={timestamp_int()}', - catch_response=True) + + # 1035 /rest/projects/1.0/project/{project_key}/lastVisited + locust.client.put(f'/rest/projects/1.0/project/{project_key}/lastVisited', + {"id": f"com.pyxis.greenhopper.jira:project-sidebar-work-{project_plan}"}, + catch_response=True) + + # 1040 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("1040"), + headers=RESOURCE_HEADERS, + catch_response=True) else: + # 1045 /rest/greenhopper/1.0/xboard/toolSections locust.get(f'/rest/greenhopper/1.0/xboard/toolSections?mode=work&rapidViewId={board_id}' - f'&_={timestamp_int()}', catch_response=True) - if view_backlog: - locust.get(f'/rest/greenhopper/1.0/xboard/plan/backlog/data.json?rapidViewId={board_id}', - catch_response=True) - else: - locust.get(f'/rest/greenhopper/1.0/xboard/work/allData.json?rapidViewId={board_id}', catch_response=True) - - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("1025"), - headers=RESOURCE_HEADERS, catch_response=True) - locust.post('/rest/webResources/1.0/resources', json=params.resources_body.get("1030"), - headers=RESOURCE_HEADERS, catch_response=True) - if view_backlog: - locust.get(f'/rest/greenhopper/1.0/rapidviewconfig/editmodel.json?rapidViewId={board_id}' - f'&_={timestamp_int()}', catch_response=True) + f'&_={timestamp_int()}', + catch_response=True) + + # 1050 /rest/greenhopper/1.0/xboard/work/allData.json + locust.get(f'/rest/greenhopper/1.0/xboard/work/allData.json?rapidViewId={board_id}', catch_response=True) + + if project_id: + # 1055 /rest/greenhopper/1.0/xboard/work/transitions.json + locust.get(f'/rest/greenhopper/1.0/xboard/work/transitions.json?' + f'projectId={project_id}' + f'&_={timestamp_int()}') + + # 1060 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("1060"), + headers=RESOURCE_HEADERS, + catch_response=True) + if project_key: + # 1065 /rest/projects/1.0/project/{project_key}/lastVisited locust.client.put(f'/rest/projects/1.0/project/{project_key}/lastVisited', {"id": f"com.pyxis.greenhopper.jira:project-sidebar-work-{project_plan}"}, catch_response=True) + + +def scrum_board(locust, board_id): + + params = ViewBoard(action_name='view_scrum_board') + + # 1100 /secure/RapidBoard.jspa + r = locust.get(f'/secure/RapidBoard.jspa?rapidView={board_id}', catch_response=True) + + content = r.content.decode('utf-8') + project_key = fetch_by_re(params.project_key_pattern, content) + project_id = fetch_by_re(params.project_id_pattern, content) + project_plan = fetch_by_re(params.project_plan_pattern, content, group_no=2) + if project_plan: + project_plan = project_plan.replace('\\', '') + logger.locust_info(f"{params.action_name}: key = {project_key}, id = {project_id}, plan = {project_plan}") + assert f'currentViewConfig\"{{\"id\":{board_id}', 'Could not open board' + + # 1110 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("1110"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1115 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("1115"), + headers=RESOURCE_HEADERS, + catch_response=True) + + if project_key: + # 1105 /rest/greenhopper/1.0/xboard/work/allData.json + locust.get(f'/rest/greenhopper/1.0/xboard/work/allData.json?' + f'rapidViewId={board_id}' + f'&selectedProjectKey={project_key}', + catch_response=True) + + # 1120 /rest/api/2/project/{x_project_key} + locust.get(f'/rest/api/2/project/{project_key}?' + f'_={timestamp_int()}', + catch_response=True) + + # 1125 /rest/greenhopper/1.0/xboard/toolSections + locust.get(f'/rest/greenhopper/1.0/xboard/toolSections?' + f'mode=work' + f'&rapidViewId={board_id}' + f'&selectedProjectKey={project_key}' + f'&_={timestamp_int()}', + catch_response=True) + + # 1130 /rest/greenhopper/1.0/xboard/work/allData.json + locust.get(f'/rest/greenhopper/1.0/xboard/work/allData.json?' + f'rapidViewId={board_id}' + f'&selectedProjectKey={project_key}', + catch_response=True) + + # 1060 /rest/projects/1.0/project/{project_key}/lastVisited + locust.client.put(f'/rest/projects/1.0/project/{project_key}/lastVisited', + {"id": f"com.pyxis.greenhopper.jira:project-sidebar-work-{project_plan}"}, + catch_response=True) + + if not project_key: + # 1140 /rest/greenhopper/1.0/xboard/toolSections + locust.get(f'/rest/greenhopper/1.0/xboard/toolSections?' + f'mode=work' + f'&rapidViewId={board_id}' + f'&_={timestamp_int()}', + catch_response=True) + + # 1145 /rest/greenhopper/1.0/xboard/work/allData.json + locust.get(f'/rest/greenhopper/1.0/xboard/work/allData.json?' + f'rapidViewId={board_id}', + catch_response=True) + + # 1150 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("1150"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1155 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("1155"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1165 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("1165"), + headers=RESOURCE_HEADERS, + catch_response=True) + + +def backlog_board(locust, board_id): + + params = ViewBoard(action_name='view_backlog') + + # 1200 /secure/RapidBoard.jspa + r = locust.get(f'/secure/RapidBoard.jspa?' + f'rapidView={board_id}' + f'&view=planning', + catch_response=True) + + content = r.content.decode('utf-8') + project_key = fetch_by_re(params.project_key_pattern, content) + project_id = fetch_by_re(params.project_id_pattern, content) + project_plan = fetch_by_re(params.project_plan_pattern, content, group_no=2) + if project_plan: + project_plan = project_plan.replace('\\', '') + logger.locust_info(f"{params.action_name}: key = {project_key}, id = {project_id}, plan = {project_plan}") + assert f'currentViewConfig\"{{\"id\":{board_id}', 'Could not open board' + + # 1210 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("1210"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1215 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("1215"), + headers=RESOURCE_HEADERS, + catch_response=True) + + if project_key: + # 1205 /rest/greenhopper/1.0/xboard/plan/backlog/data.json + locust.get(f'/rest/greenhopper/1.0/xboard/plan/backlog/data.json?' + f'rapidViewId={board_id}' + f'&selectedProjectKey={project_key}', + catch_response=True) + + # 1235 /rest/api/2/project/{project_key} + locust.get(f'/rest/api/2/project/{project_key}?_={timestamp_int()}', catch_response=True) + + # 1240 /rest/greenhopper/1.0/xboard/toolSections + locust.get(f'/rest/greenhopper/1.0/xboard/toolSections?' + f'mode=plan' + f'&rapidViewId={board_id}' + f'&selectedProjectKey={project_key}' + f'&_={timestamp_int()}', + catch_response=True) + + # 1245 /rest/greenhopper/1.0/xboard/plan/backlog/data.json + locust.get(f'/rest/greenhopper/1.0/xboard/plan/backlog/data.json?' + f'&rapidViewId={board_id}' + f'&selectedProjectKey={project_key}' + f'&_={timestamp_int()}', + catch_response=True) + + # 1250 /rest/inline-create/1.0/context/bootstrap + locust.get(f'/rest/inline-create/1.0/context/bootstrap?' + f'&query=project = {project_key} ORDER BY Rank ASC' + f'&_={timestamp_int()}', + catch_response=True) + + # 1255 /rest/webResources/1.0/resources + locust.post('/rest/webResources/1.0/resources', + json=params.resources_body.get("1255"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1260 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("1260"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1265 /rest/analytics/1.0/publish/bulk + locust.post('/rest/analytics/1.0/publish/bulk', + json=params.resources_body.get("1265"), + headers=RESOURCE_HEADERS, + catch_response=True) + + # 1285 /rest/projects/1.0/project/{project_key}/lastVisited + locust.client.put(f'/rest/projects/1.0/project/{project_key}/lastVisited', + {"id": f"com.pyxis.greenhopper.jira:project-sidebar-work-{project_plan}"}, + catch_response=True) + + if not project_key: + # 1270 /rest/greenhopper/1.0/xboard/toolSections + locust.get(f'/rest/greenhopper/1.0/xboard/toolSections?' + f'mode=plan' + f'&rapidViewId={board_id}' + f'&_={timestamp_int()}', + catch_response=True) + + # 1275 /rest/greenhopper/1.0/xboard/plan/backlog/data.json + locust.get(f'/rest/greenhopper/1.0/xboard/plan/backlog/data.json?' + f'rapidViewId={board_id}', + catch_response=True) + + # 1280 /rest/greenhopper/1.0/rapidviewconfig/editmodel.json + locust.get(f'/rest/greenhopper/1.0/rapidviewconfig/editmodel.json?' + f'rapidViewId={board_id}' + f'&_={timestamp_int()}', + catch_response=True) diff --git a/app/locustio/jira/requests_params.py b/app/locustio/jira/requests_params.py index b96b653d9..0e7215992 100644 --- a/app/locustio/jira/requests_params.py +++ b/app/locustio/jira/requests_params.py @@ -38,8 +38,8 @@ class Login(JiraResource): } - class BrowseIssue(JiraResource): + action_name = "view_issue" issue_id_pattern = r'id="key-val" rel="(.+?)">' project_avatar_id_pattern = r'projectavatar\?avatarId\=(.+?)" ' edit_allow_pattern = "secure\/EditLabels\!default" # noqa W605 @@ -51,6 +51,7 @@ class ViewDashboard(JiraResource): class CreateIssue(JiraResource): + action_name = 'create_issue' atl_token_pattern = '"atl_token":"(.+?)"' form_token_pattern = '"formToken":"(.+?)"' issue_type_pattern = '\{"label":"Story","value":"([0-9]*)"' # noqa W605 @@ -58,8 +59,8 @@ class CreateIssue(JiraResource): resolution_done_pattern = r'<option value=\\"([0-9]*)\\">\\n Done\\n' fields_to_retain_pattern = '"id":"([a-z]*)","label":"[A-Za-z0-9\- ]*","required":(false|true),' # noqa W605 custom_fields_to_retain_pattern = '"id":"customfield_([0-9]*)","label":"[A-Za-z0-9\- ]*","required":(false|true),' # noqa W605 - user_preferences_payload = {"useQuickForm": False, "fields": ["summary", "description", - "priority", "versions", "components"], + user_preferences_payload = {"useQuickForm": False, + "fields": ["summary", "description", "priority", "versions", "components"], "showWelcomeScreen": True} create_issue_key_pattern = '"issueKey":"(.+?)"' err_message_create_issue = 'Issue was not created' @@ -142,6 +143,7 @@ class AddComment(JiraResource): action_name = 'add_comment' form_token_pattern = 'name="formToken"\s*type="hidden"\s*value="(.+?)"' # noqa W605 atl_token_pattern = r'name="atlassian-token" content="(.+?)">' + browse_project_payload = {"id": "com.atlassian.jira.jira-projects-issue-navigator:sidebar-issue-navigator"} class BrowseProjects(JiraResource): @@ -149,11 +151,16 @@ class BrowseProjects(JiraResource): class ViewBoard(JiraResource): - action_name = 'view_kanban_board' + + def __init__(self, action_name): + self.action_name = action_name + super().__init__() + project_key_pattern = '\["project-key"\]=\"\\\\"(.+?)\\\\""' # noqa W605 project_id_pattern = '\["project-id"\]=\"(.+?)\"' # noqa W605 project_plan_pattern = 'com.pyxis.greenhopper.jira:project-sidebar-(.+?)-(.+?)"' class BrowseBoards(JiraResource): + action_name = 'browse_boards' diff --git a/app/locustio/jira/resources.json b/app/locustio/jira/resources.json index abb9118f7..18c49bf14 100644 --- a/app/locustio/jira/resources.json +++ b/app/locustio/jira/resources.json @@ -1,698 +1,90 @@ { "login_and_view_dashboard": { - "110": { - "r": [], - "c": [ - "browser-metrics-plugin.contrib" - ], - "xc": [ - "_super", - "atl.dashboard", - "jira.global", - "atl.general", - "jira.general" - ], - "xr": [ - "com.atlassian.jira.jira-postsetup-announcements-plugin:post-setup-announcements", - "com.atlassian.gadgets.dashboard:gadgets-adgs", - "com.atlassian.jira.jira-issue-nav-components:adgs", - "com.atlassian.jira.jira-issue-nav-components:detailslayout-adgs", - "com.atlassian.jira.jira-issue-nav-components:simpleissuelist-adgs", - "com.atlassian.jira.jira-issue-nav-plugin:adgs-styles", - "com.atlassian.jira.jira-issue-nav-components:orderby-less-adgs", - "com.atlassian.jira.jira-issue-nav-components:pager-less-adgs", - "com.atlassian.jira.jira-issue-nav-components:issueviewer-adgs", - "com.atlassian.jira.gadgets:introduction-dashboard-item-resource-adgs" - ] - }, - "120": { - "r": [], - "c": [ - "jira.webresources:mentions-feature" - ], - "xc": [ - "_super", - "atl.dashboard", - "jira.global", - "atl.general", - "jira.general", - "browser-metrics-plugin.contrib", - "atl.global", - "jira.dashboard", - "jira.global.look-and-feel" - ], - "xr": [ - "com.atlassian.jira.jira-postsetup-announcements-plugin:post-setup-announcements", - "com.atlassian.gadgets.dashboard:gadgets-adgs", - "com.atlassian.jira.jira-issue-nav-components:adgs", - "com.atlassian.jira.jira-issue-nav-components:detailslayout-adgs", - "com.atlassian.jira.jira-issue-nav-components:simpleissuelist-adgs", - "com.atlassian.jira.jira-issue-nav-plugin:adgs-styles", - "com.atlassian.jira.jira-issue-nav-components:orderby-less-adgs", - "com.atlassian.jira.jira-issue-nav-components:pager-less-adgs", - "com.atlassian.jira.jira-issue-nav-components:issueviewer-adgs", - "com.atlassian.jira.gadgets:introduction-dashboard-item-resource-adgs", - "com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component", - "com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib", - "com.atlassian.jira.jira-postsetup-announcements-plugin:post-setup-announcements-lib", - "jira.webresources:calendar-en", - "jira.webresources:calendar-localisation-moment", - "jira.webresources:bigpipe-js", - "jira.webresources:bigpipe-init" - ] - }, - "125": { - "r": [ - "com.atlassian.jira.jira-header-plugin:newsletter-signup-tip" - ], - "c": [ - "com.atlassian.jira.plugins.jira-development-integration-plugin:0" - ], - "xc": [ - "_super", - "atl.dashboard", - "jira.global", - "atl.general", - "jira.general", - "browser-metrics-plugin.contrib", - "atl.global", - "jira.dashboard", - "jira.global.look-and-feel" - ], - "xr": [ - "com.atlassian.jira.jira-postsetup-announcements-plugin:post-setup-announcements", - "com.atlassian.gadgets.dashboard:gadgets-adgs", - "com.atlassian.jira.jira-issue-nav-components:adgs", - "com.atlassian.jira.jira-issue-nav-components:detailslayout-adgs", - "com.atlassian.jira.jira-issue-nav-components:simpleissuelist-adgs", - "com.atlassian.jira.jira-issue-nav-plugin:adgs-styles", - "com.atlassian.jira.jira-issue-nav-components:orderby-less-adgs", - "com.atlassian.jira.jira-issue-nav-components:pager-less-adgs", - "com.atlassian.jira.jira-issue-nav-components:issueviewer-adgs", - "com.atlassian.jira.gadgets:introduction-dashboard-item-resource-adgs", - "com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component", - "com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib", - "com.atlassian.jira.jira-postsetup-announcements-plugin:post-setup-announcements-lib", - "jira.webresources:calendar-en", - "jira.webresources:calendar-localisation-moment", - "jira.webresources:bigpipe-js", - "jira.webresources:bigpipe-init" - ] - }, - "130": { - "r": [], - "c": [ - "browser-metrics-plugin.contrib" - ], - "xc": [ - "jira.webresources:almond", - "jira.webresources:aui-core-amd-shim", - "jira.webresources:jira-metadata", - "jira.webresources:jquery-livestamp", - "com.atlassian.auiplugin:ajs-underscorejs", - "com.atlassian.analytics.analytics-client:js-events", - "com.atlassian.plugins.browser.metrics.browser-metrics-plugin:api", - "com.atlassian.gadgets.publisher:ajs-gadgets", - "com.atlassian.streams:streamsGadgetResources" - ], - "xr": [ - "jira.webresources:icons", - "jira.webresources:list-styles", - "jira.webresources:inline-layer", - "jira.webresources:dropdown", - "com.atlassian.auiplugin:aui-lozenge", - "com.atlassian.auiplugin:aui-tipsy", - "com.atlassian.auiplugin:aui-tooltips", - "com.atlassian.plugins.issue-status-plugin:issue-status-resources", - "jira.webresources:frother-queryable-dropdown-select", - "jira.webresources:frother-singleselect", - "jira.webresources:frother-multiselect", - "jira.webresources:frother-checkbox-multiselect", - "jira.webresources:select-pickers", - "jira.webresources:autocomplete", - "com.atlassian.jira.gadgets:core-gadget-resources" - ] - } + "110": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","atl.dashboard","jira.global","atl.general","jira.dashboard"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component"]}, + "115": {"r":[],"c":["com.atlassian.jira.plugins.jira-development-integration-plugin:8","jira.webresources:mentions-feature","com.atlassian.jira.plugins.jira-development-integration-plugin:0"],"xc":["_super","atl.dashboard","jira.global","atl.general","jira.dashboard","browser-metrics-plugin.contrib","atl.global","jira.global.look-and-feel"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:calendar-en","jira.webresources:calendar-localisation-moment","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init"]}, + "120": [{"name":"quicksearch.enabled","properties":{},"timeDelta":-1044},{"name":"atst.healthcheck.sensors.page-protocols","properties":{"resourceProtocols":"http/1.1","navigationProtocol":"http/1.1","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36"},"timeDelta":-685}], + "125": [{"name":"browser.metrics.navigation","properties":{"apdex":"0","firstPaint":"2331","isInitial":"true","journeyId":"68d353c0-5dc0-449b-a7ce-f348f8a8372b","key":"jira.dashboard","navigationType":"0","readyForUser":"6584","redirectCount":"1","resourceLoadedEnd":"1723","resourceLoadedStart":622.4300000176299,"threshold":"1000","unloadEventStart":"514","unloadEventEnd":"517","redirectStart":"5","redirectEnd":"341","fetchStart":"341","domainLookupStart":"341","domainLookupEnd":"341","connectStart":"341","connectEnd":"341","requestStart":"344","responseStart":"495","responseEnd":"620","domLoading":"527","domInteractive":"2427","domContentLoadedEventStart":"2428","domContentLoadedEventEnd":"2710","domComplete":"6612","loadEventStart":"6614","loadEventEnd":"6631","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36","correlationId":"ea0357911b5724","effectiveType":"4g","downlink":5.9,"rtt":100,"serverDuration":"42","dbConnsTimeInMs":"6","applicationHash":"e00b0abe8f1b188f0bb304a4c3b424f1180ba767","resourceTiming":"{\"☠\":[\"2,ha,ps,l9,hl,ha,,ha,ha,ha\",\"2,hb,w6,ld,hr,hb,,hb,hb,hb\",\"2,hc,op,om,l5,l5,,hp,hp,hp\",\"3,hd,16t,pk,lg,lc,,hq,hq,hq\",\"3,hd,14k,pn,lg,lc,,hq,hq,hq\",\"3,he,te,tb,ps,he,,he,he,he\",\"3,hf,tv,tr,pz,hf,,hf,hf,hf\",\"3,hg,tu,tj,q0,hg,,hg,hg,hg\",\"3,hh,xa,x3,te,hh,,hh,hh,hh\",\"3,hh,xw,xn,tx,hh,,hh,hh,hh\",\"2,hi,pt,p4,lf,l9,,ia,ia,ia\",\"3,hj,xw,xs,u3,hj,,hj,hj,hj\",\"3,hk,1az,1ar,16v,hk,,hk,hk,hk\",\"3,l8,1bv,1bp,182,l8,,l8,l8,l8\",\"5,1kj,1of,1ob,1kn,1kj,,1kj,1kj,1kj\",\"4,1ns,1wm,1wj,1sy,1ns,,1ns,1ns,1ns\",\"5,20p,25i,25c,20v,20p,,20p,20p,20p\",\"-1,226,26m,26e,22o,226,,226,226,226\",\"5,232,26t,26r,236,232,,232,232,232\",\"3,24m,29b,294,25j,24m,,24m,24m,24m\",\"5,2r1,2v1,2uw,2ra,2r1,,2r1,2r1,2r1\",\"5,2s0,2yi,2x8,2t6,2s0,,2s0,2s0,2s0\",\"2,2zb,3ch,3bj,381,2zb,,2zb,2zb,2zb\",\"2,2zm,3cv,3bz,382,2zm,,2zm,2zm,2zm\",\"3,2zs,4kv,4km,4h4,2zs,,2zs,2zs,2zs\",\"3,2zv,4o3,4ny,4k6,2zv,,2zv,2zv,2zv\"]}","userTimingRaw":"{\"marks\":{},\"measures\":{}}","experiments":"[]","dbReadsTimeInMs":"","serverHeadDuration":"undefined","connectionEffectiveType":"4g","connectionDownlink":5.9,"connectionRTT":100},"timeDelta":-1602}] + }, + "create_issue": { + "210": [{"name":"jira.wikieditor.initialized","properties":{},"timeDelta":-3120},{"name":"jira.wikieditor.initialized","properties":{},"timeDelta":-2842},{"name":"jira.wikieditor.initialized","properties":{},"timeDelta":-2495},{"name":"browser.metrics.navigation","properties":{"apdex":"1","isInitial":"false","journeyId":"68d353c0-5dc0-449b-a7ce-f348f8a8372b","key":"jira.dialog.open.create-issue-dialog","readyForUser":"897","threshold":"1000","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36","effectiveType":"4g","downlink":1.45,"rtt":100,"applicationHash":"e00b0abe8f1b188f0bb304a4c3b424f1180ba767","resourceTiming":"{\"☠\":[\"5,7,7w,7q,a,7,,7,7,7\"]}","userTimingRaw":"{\"marks\":{},\"measures\":{}}","experiments":"[]","connectionEffectiveType":"4g","connectionDownlink":1.45,"connectionRTT":100},"timeDelta":-1996},{"name":"issue.dnd.attachment.createissuedropzone.init","properties":{},"timeDelta":-1597},{"name":"jira.wikieditor.initialized","properties":{},"timeDelta":-1593},{"name":"editor.instance.init","properties":{},"timeDelta":-1466},{"name":"bundled.editor.instance.init","properties":{},"timeDelta":-1466},{"name":"editor.instance.init.chrome","properties":{},"timeDelta":-1465},{"name":"editor.instance.init","properties":{},"timeDelta":-1326},{"name":"bundled.editor.instance.init","properties":{},"timeDelta":-1326},{"name":"editor.instance.init.chrome","properties":{},"timeDelta":-1326},{"name":"editor.instance.init","properties":{},"timeDelta":-1270},{"name":"bundled.editor.instance.init","properties":{},"timeDelta":-1270},{"name":"editor.instance.init.chrome","properties":{},"timeDelta":-1270},{"name":"editor.instance.perf.nodechange","properties":{"time":28.130000000353903},"timeDelta":-869},{"name":"editor.instance.perf.init","properties":{"time":1538.2599999997765},"timeDelta":-763},{"name":"editor.instance.init.perf","properties":{"time":140.08499999996275},"timeDelta":-763},{"name":"editor.instance.perf.init-bare","properties":{"time":1538.619999999646},"timeDelta":-763},{"name":"editor.instance.perf.nodechange","properties":{"time":4.289999999571592},"timeDelta":-736},{"name":"editor.instance.perf.nodechange","properties":{"time":2.3449999997392297},"timeDelta":-712},{"name":"editor.instance.perf.nodechange","properties":{"time":4.5750000001862645},"timeDelta":-677},{"name":"editor.instance.perf.init","properties":{"time":1653.3499999996275},"timeDelta":-648},{"name":"editor.instance.init.perf","properties":{"time":35.544999999925494},"timeDelta":-648},{"name":"editor.instance.perf.init-bare","properties":{"time":1653.5099999997765},"timeDelta":-648},{"name":"editor.instance.perf.nodechange","properties":{"time":15.514999999664724},"timeDelta":-616},{"name":"editor.instance.perf.nodechange","properties":{"time":1.4600000004284084},"timeDelta":-605},{"name":"editor.instance.perf.nodechange","properties":{"time":2.390000000130385},"timeDelta":-591},{"name":"editor.instance.perf.init","properties":{"time":1724.1399999996647},"timeDelta":-578},{"name":"editor.instance.init.perf","properties":{"time":16.674999999813735},"timeDelta":-578},{"name":"editor.instance.perf.init-bare","properties":{"time":1724.2199999997392},"timeDelta":-578},{"name":"editor.instance.perf.nodechange","properties":{"time":1.339999999385327},"timeDelta":-571},{"name":"editor.instance.perf.nodechange","properties":{"time":1.3500000000931323},"timeDelta":-557}], + "220": [{"name":"quick.create.fields","properties":{"atlassian.numCreates":1,"edit.form":false,"pid":"added","issuetype":"added","formToken":"added","resolution":"added","worklog_startDate":"added","worklog_adjustEstimate":"added","issuelinks":"added","issuelinks-linktype":"added","assignee":"added","summary":"added","priority":"added","customfield_10551":"added"},"timeDelta":-787},{"name":"quickeditform.submit.success","properties":{"allFieldsShown":true,"allFields":"[{\"id\":\"project\",\"required\":true},{\"id\":\"issuetype\",\"required\":true},{\"id\":\"components\",\"required\":false},{\"id\":\"versions\",\"required\":false},{\"id\":\"resolution\",\"required\":false},{\"id\":\"attachment\",\"required\":false},{\"id\":\"labels\",\"required\":false},{\"id\":\"worklog\",\"required\":false},{\"id\":\"issuelinks\",\"required\":false},{\"id\":\"fixVersions\",\"required\":false},{\"id\":\"assignee\",\"required\":false},{\"id\":\"environment\",\"required\":false},{\"id\":\"description\",\"required\":false},{\"id\":\"timetracking\",\"required\":false},{\"id\":\"summary\",\"required\":true},{\"id\":\"priority\",\"required\":false},{\"id\":\"duedate\",\"required\":false},{\"id\":\"customfield_10513\",\"required\":false},{\"id\":\"customfield_10551\",\"required\":false},{\"id\":\"customfield_10633\",\"required\":false},{\"id\":\"customfield_10694\",\"required\":false},{\"id\":\"customfield_10717\",\"required\":false}]","displayedFields":"[{\"id\":\"project\",\"required\":true},{\"id\":\"issuetype\",\"required\":true},{\"id\":\"components\",\"required\":false},{\"id\":\"versions\",\"required\":false},{\"id\":\"resolution\",\"required\":false},{\"id\":\"attachment\",\"required\":false},{\"id\":\"labels\",\"required\":false},{\"id\":\"worklog\",\"required\":false},{\"id\":\"issuelinks\",\"required\":false},{\"id\":\"fixVersions\",\"required\":false},{\"id\":\"assignee\",\"required\":false},{\"id\":\"environment\",\"required\":false},{\"id\":\"description\",\"required\":false},{\"id\":\"timetracking\",\"required\":false},{\"id\":\"summary\",\"required\":true},{\"id\":\"priority\",\"required\":false},{\"id\":\"duedate\",\"required\":false},{\"id\":\"customfield_10513\",\"required\":false},{\"id\":\"customfield_10551\",\"required\":false},{\"id\":\"customfield_10633\",\"required\":false},{\"id\":\"customfield_10694\",\"required\":false},{\"id\":\"customfield_10717\",\"required\":false}]"},"timeDelta":-786},{"name":"editor.instance.tab.timing.visual","properties":{"time":20977.28000000026},"timeDelta":-435},{"name":"editor.instance.tab.timing.visual","properties":{"time":20979.60499999998},"timeDelta":-433},{"name":"editor.instance.tab.timing.visual","properties":{"time":20982.985000000335},"timeDelta":-429},{"name":"editor.instance.destroy","properties":{},"timeDelta":-239},{"name":"bundled.editor.instance.destroy","properties":{},"timeDelta":-238},{"name":"editor.instance.destroy","properties":{},"timeDelta":-234},{"name":"bundled.editor.instance.destroy","properties":{},"timeDelta":-234},{"name":"editor.instance.destroy","properties":{},"timeDelta":-222},{"name":"bundled.editor.instance.destroy","properties":{},"timeDelta":-222}] }, "search_jql": { - "305": { - "r": [ - ], - "c": [ - "browser-metrics-plugin.contrib" - ], - "xc": [ - "_super", - "jira.view.issue", - "jira.navigator.kickass", - "viewissue.standalone", - "jira.navigator.simple", - "jira.navigator.advanced", - "atl.general", - "jira.general", - "jira.global" - ], - "xr": [ - "jira.filter.deletion.warning:styles" - ] - }, - "320": { - "r": [ - "com.atlassian.jira.plugins.jira-editor-plugin:api", - "com.atlassian.jira.plugins.jira-editor-plugin:resources", - "com.atlassian.jira.plugins.jira-editor-plugin:converter" - ], - "c": [ - "jira.webresources:mentions-feature", - "jira.rich.editor" - ], - "xc": [ - "_super", - "jira.view.issue", - "jira.navigator.kickass", - "viewissue.standalone", - "jira.navigator.simple", - "jira.navigator.advanced", - "atl.general", - "jira.general", - "jira.global", - "browser-metrics-plugin.contrib", - "atl.global", - "jira.global.look-and-feel" - ], - "xr": [ - "jira.filter.deletion.warning:styles", - "com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component", - "com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib", - "jira.webresources:calendar-en", - "jira.webresources:calendar-localisation-moment", - "jira.webresources:bigpipe-js", - "jira.webresources:bigpipe-init" - ] - }, - "330": { - "r": [ - "com.atlassian.jira.jira-header-plugin:newsletter-signup-tip" - ], - "c": [ - ], - "xc": [ - "_super", - "jira.view.issue", - "jira.navigator.kickass", - "viewissue.standalone", - "jira.navigator.simple", - "jira.navigator.advanced", - "atl.general", - "jira.general", - "jira.global", - "browser-metrics-plugin.contrib", - "atl.global", - "jira.global.look-and-feel", - "jira.rich.editor" - ], - "xr": [ - "jira.filter.deletion.warning:styles", - "com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component", - "com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib", - "jira.webresources:calendar-en", - "jira.webresources:calendar-localisation-moment", - "jira.webresources:bigpipe-js", - "jira.webresources:bigpipe-init", - "com.atlassian.jira.plugins.jira-editor-plugin:tinymce", - "com.atlassian.jira.plugins.jira-editor-plugin:schema-builder", - "com.atlassian.jira.plugins.jira-editor-plugin:schema", - "com.atlassian.jira.plugins.jira-editor-plugin:i18n", - "com.atlassian.jira.plugins.jira-editor-plugin:wrm", - "com.atlassian.jira.plugins.jira-editor-plugin:converter-util", - "com.atlassian.jira.plugins.jira-editor-plugin:context-detector", - "com.atlassian.jira.plugins.jira-editor-plugin:context-manager", - "com.atlassian.jira.plugins.jira-editor-plugin:selection", - "com.atlassian.jira.plugins.jira-editor-plugin:instance", - "com.atlassian.jira.plugins.jira-editor-plugin:api", - "com.atlassian.jira.plugins.jira-editor-plugin:renderer", - "com.atlassian.jira.plugins.jira-editor-plugin:mentions", - "com.atlassian.jira.plugins.jira-editor-plugin:mentions-plugin", - "com.atlassian.jira.plugins.jira-editor-plugin:polyfil-string-ends-with", - "com.atlassian.jira.plugins.jira-editor-plugin:resources", - "com.atlassian.jira.plugins.jira-editor-plugin:converter" - ] - } + "305": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","jira.view.issue","viewissue.standalone","jira.navigator.kickass","jira.global","jira.navigator","atl.general","jira.navigator.simple","jira.navigator.advanced"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","jira.filter.deletion.warning:styles"]}, + "310": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","jira.view.issue","viewissue.standalone","jira.navigator.kickass","jira.global","jira.navigator","atl.general","jira.navigator.simple","jira.navigator.advanced"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","jira.filter.deletion.warning:styles"]}, + "315": {"r":[],"c":["com.atlassian.jira.plugins.jira-development-integration-plugin:0"],"xc":["_super","jira.view.issue","viewissue.standalone","jira.navigator.kickass","jira.global","jira.navigator","atl.general","jira.navigator.simple","jira.navigator.advanced","browser-metrics-plugin.contrib","atl.global","jira.global.look-and-feel","com.atlassian.jira.plugins.jira-development-integration-plugin:7","jira.rich.editor.api","jira.rich.editor"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","jira.filter.deletion.warning:styles","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:calendar-en","jira.webresources:calendar-localisation-moment","jira.webresources:bigpipe-js","com.atlassian.jira.plugins.jira-editor-plugin:tinymce","jira.webresources:bigpipe-init"]}, + "320": [{"name":"kickass.criteriaAutoUpdateEnabled","properties":{"enabled":true},"timeDelta":-1457},{"name":"kickass.issue-navigator.change-layout","properties":{"type":"split-view"},"timeDelta":-1024},{"name":"quicksearch.enabled","properties":{},"timeDelta":-960}],"325":[{"name":"devstatus.issue-navigator.dev-info.shown","properties":{},"timeDelta":-5328},{"name":"kickass.viewIssue","properties":{"issueId":205554,"loadedFromDom":false,"source":"jira.issuenav.global","projectId":10263,"projectType":"software","issueMatchesProjectContext":true},"timeDelta":-4688},{"name":"issue.dnd.attachment.attachmentsdropzone.init","properties":{},"timeDelta":-4341},{"name":"jira.wikieditor.initialized","properties":{},"timeDelta":-4324},{"name":"browser.metrics.navigation","properties":{"apdex":"0","firstPaint":"2120","isInitial":"true","journeyId":"68d353c0-5dc0-449b-a7ce-f348f8a8372b","key":"jira.issue.nav-detail","navigationType":"0","readyForUser":"4725","redirectCount":"1","resourceLoadedEnd":"2488","resourceLoadedStart":564.7950000002311,"threshold":"1000","unloadEventStart":"450","unloadEventEnd":"450","redirectStart":"2","redirectEnd":"269","fetchStart":"269","domainLookupStart":"269","domainLookupEnd":"269","connectStart":"269","connectEnd":"269","requestStart":"272","responseStart":"421","responseEnd":"1790","domLoading":"482","domInteractive":"2494","domContentLoadedEventStart":"2494","domContentLoadedEventEnd":"3191","domComplete":"5769","loadEventStart":"5770","loadEventEnd":"5781","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36","correlationId":"8c41587a7d6686","effectiveType":"4g","downlink":10,"rtt":50,"serverDuration":"1255","dbReadsTimeInMs":"875","dbConnsTimeInMs":"901","applicationHash":"e00b0abe8f1b188f0bb304a4c3b424f1180ba767","resourceTiming":"{\"☠\":[\"2,fo,ov,jo,fy,fo,,fo,fo,fo\",\"2,fp,vt,ns,jf,jf,,g0,g0,g0\",\"2,fq,ny,nn,jm,jl,,g6,g6,g6\",\"2,fq,nz,nv,jn,jm,,g6,g6,g6\",\"3,fr,19k,ru,o1,fr,,fr,fr,fr\",\"3,fr,17q,rr,o2,fr,,fr,fr,fr\",\"3,fs,s5,rl,o3,fs,,fs,fs,fs\",\"3,fs,sp,sj,ov,fs,,fs,fs,fs\",\"3,ft,w2,vv,s7,ft,,ft,ft,ft\",\"3,ft,wk,wd,sr,ft,,ft,ft,ft\",\"3,fu,zo,zn,w5,fu,,fu,fu,fu\",\"2,fu,nx,nl,jn,jm,,g6,g6,g6\",\"3,fv,zs,zq,w7,fv,,fv,fv,fv\",\"5,1h8,1l0,1ky,1hb,1h8,,1h8,1h8,1h8\",\"4,1kt,1rx,1rv,1o5,1kt,,1kt,1kt,1kt\",\"4,1ph,1t9,1t2,1pk,1ph,,1ph,1ph,1ph\",\"3,1s8,1vx,1vt,1sb,1s8,,1s8,1s8,1s8\",\"3,1t9,1x2,1x1,1ti,1t9,,1t9,1t9,1t9\",\"3,1t9,1x4,1x3,1tm,1t9,,1t9,1t9,1t9\",\"5,1w7,20d,20b,1wb,1w7,,1w7,1w7,1w7\",\"5,20v,24n,24l,20z,20v,,20v,20v,20v\",\"5,28z,2cx,2cs,296,28z,,28z,28z,28z\",\"5,2cy,2j6,2j2,2da,2cy,,2cy,2cy,2cy\",\"2,2hr,2ll,2lh,2hw,2hr,,2hr,2hr,2hr\",\"3,2ht,2t9,2ll,2i0,2ht,,2ht,2ht,2ht\",\"3,2hw,2pn,2lv,2i3,2hw,,2hw,2hw,2hw\",\"3,2i0,2m1,2lr,2i3,2i0,,2i0,2i0,2i0\",\"3,2i2,2mu,2ms,2jb,2i2,,2i2,2i2,2i2\",\"5,2n4,2rh,2re,2na,2n4,,2n4,2n4,2n4\",\"5,2ys,3ai,3a1,2yv,2ys,,2ys,2ys,2ys\",\"5,346,3eg,3ee,3ap,346,,346,346,346\",\"5,34g,3ia,3hv,3aq,34g,,34g,34g,34g\",\"5,3a5,3eg,3ea,3an,3a5,,3a5,3a5,3a5\"]}","userTimingRaw":"{\"marks\":{},\"measures\":{}}","experiments":"[]","serverHeadDuration":"undefined","connectionEffectiveType":"4g","connectionDownlink":10,"connectionRTT":50},"timeDelta":-3432}] }, - "view_project_summary": { - "505": { - "r": [ - ], - "c": [ - "browser-metrics-plugin.contrib" - ], - "xc": [ - "_super", - "com.atlassian.jira.project.summary.page", - "jira.project.sidebar", - "com.atlassian.jira.projects.sidebar.init", - "atl.general", - "jira.general", - "jira.global" - ], - "xr": [ - "jira.webresources:calendar-lib", - "jira.webresources:autocomplete", - "jira.webresources:groupbrowser", - "jira.webresources:group-pickers", - "com.atlassian.auiplugin:aui-labels", - "jira.webresources:global-static-adgs", - "jira.webresources:global-static" - ] - }, - "510": { - "r": [ - ], - "c": [ - "browser-metrics-plugin.contrib" - ], - "xc": [ - "jira.webresources:almond", - "jira.webresources:aui-core-amd-shim", - "jira.webresources:jira-metadata", - "jira.webresources:jquery-livestamp", - "com.atlassian.auiplugin:ajs-underscorejs", - "com.atlassian.analytics.analytics-client:js-events", - "com.atlassian.plugins.browser.metrics.browser-metrics-plugin:api", - "com.atlassian.gadgets.publisher:ajs-gadgets", - "com.atlassian.streams:streamsGadgetResources" - ], - "xr": [ - "jira.webresources:icons", - "jira.webresources:list-styles", - "jira.webresources:inline-layer", - "jira.webresources:dropdown", - "com.atlassian.auiplugin:aui-lozenge", - "com.atlassian.auiplugin:aui-tipsy", - "com.atlassian.auiplugin:aui-tooltips", - "com.atlassian.plugins.issue-status-plugin:issue-status-resources", - "jira.webresources:frother-queryable-dropdown-select", - "jira.webresources:frother-singleselect", - "jira.webresources:frother-multiselect", - "jira.webresources:frother-checkbox-multiselect", - "jira.webresources:select-pickers", - "jira.webresources:autocomplete", - "com.atlassian.jira.gadgets:core-gadget-resources" - ] - }, - "520": { - "r": [ - ], - "c": [ - "jira.webresources:mentions-feature" - ], - "xc": [ - "_super", - "com.atlassian.jira.project.summary.page", - "jira.project.sidebar", - "com.atlassian.jira.projects.sidebar.init", - "atl.general", - "jira.general", - "jira.global", - "browser-metrics-plugin.contrib", - "atl.global", - "jira.global.look-and-feel" - ], - "xr": [ - "jira.webresources:calendar-lib", - "jira.webresources:autocomplete", - "jira.webresources:groupbrowser", - "jira.webresources:group-pickers", - "com.atlassian.auiplugin:aui-labels", - "jira.webresources:global-static-adgs", - "jira.webresources:global-static", - "com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component", - "com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib", - "jira.webresources:calendar", - "jira.webresources:group-label-lozenge", - "jira.webresources:ie-imitation-placeholder", - "jira.webresources:jira-project-issuetype-fields", - "jira.webresources:jira-fields", - "jira.webresources:calendar-en", - "jira.webresources:calendar-localisation-moment", - "jira.webresources:bigpipe-js", - "jira.webresources:bigpipe-init" - ] - }, - "530": { - "r": [ - ], - "c": [ - "jira.project.sidebar", - "jira.project.sidebar.software" - ], - "xc": [ - "_super", - "com.atlassian.jira.project.summary.page", - "jira.project.sidebar", - "com.atlassian.jira.projects.sidebar.init", - "atl.general", - "jira.general", - "jira.global", - "browser-metrics-plugin.contrib", - "atl.global", - "jira.global.look-and-feel" - ], - "xr": [ - "jira.webresources:calendar-lib", - "jira.webresources:autocomplete", - "jira.webresources:groupbrowser", - "jira.webresources:group-pickers", - "com.atlassian.auiplugin:aui-labels", - "jira.webresources:global-static-adgs", - "jira.webresources:global-static", - "com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component", - "com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib", - "jira.webresources:calendar", - "jira.webresources:group-label-lozenge", - "jira.webresources:ie-imitation-placeholder", - "jira.webresources:jira-project-issuetype-fields", - "jira.webresources:jira-fields", - "jira.webresources:calendar-en", - "jira.webresources:calendar-localisation-moment", - "jira.webresources:bigpipe-js", - "jira.webresources:bigpipe-init" - ] - }, - "545": { - "r": [ - "com.atlassian.jira.jira-header-plugin:newsletter-signup-tip" - ], - "c": [ - ], - "xc": [ - "_super", - "com.atlassian.jira.project.summary.page", - "jira.project.sidebar", - "com.atlassian.jira.projects.sidebar.init", - "atl.general", - "jira.general", - "jira.global", - "browser-metrics-plugin.contrib", - "atl.global", - "jira.global.look-and-feel" - ], - "xr": [ - "jira.webresources:calendar-lib", - "jira.webresources:autocomplete", - "jira.webresources:groupbrowser", - "jira.webresources:group-pickers", - "com.atlassian.auiplugin:aui-labels", - "jira.webresources:global-static-adgs", - "jira.webresources:global-static", - "com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component", - "com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib", - "jira.webresources:calendar", - "jira.webresources:group-label-lozenge", - "jira.webresources:ie-imitation-placeholder", - "jira.webresources:jira-project-issuetype-fields", - "jira.webresources:jira-fields", - "jira.webresources:calendar-en", - "jira.webresources:calendar-localisation-moment", - "jira.webresources:bigpipe-js", - "jira.webresources:bigpipe-init" - ] - }, - "555": { - "r": [ - ], - "c": [ - "browser-metrics-plugin.contrib" - ], - "xc": [ - "jira.webresources:almond", - "jira.webresources:aui-core-amd-shim", - "jira.webresources:jira-metadata", - "jira.webresources:jquery-livestamp", - "com.atlassian.auiplugin:ajs-underscorejs", - "com.atlassian.analytics.analytics-client:js-events", - "com.atlassian.plugins.browser.metrics.browser-metrics-plugin:api", - "com.atlassian.gadgets.publisher:ajs-gadgets", - "com.atlassian.streams:streamsGadgetResources" - ], - "xr": [ - "jira.webresources:icons", - "jira.webresources:list-styles", - "jira.webresources:inline-layer", - "jira.webresources:dropdown", - "com.atlassian.auiplugin:aui-lozenge", - "com.atlassian.auiplugin:aui-tipsy", - "com.atlassian.auiplugin:aui-tooltips", - "com.atlassian.plugins.issue-status-plugin:issue-status-resources", - "jira.webresources:frother-queryable-dropdown-select", - "jira.webresources:frother-singleselect", - "jira.webresources:frother-multiselect", - "jira.webresources:frother-checkbox-multiselect", - "jira.webresources:select-pickers", - "jira.webresources:autocomplete", - "com.atlassian.jira.gadgets:core-gadget-resources" - ] - } + "view_issue": { + "405": {"r":[],"c":["jira.webresources:mentions-feature"],"xc":["_super","project.issue.navigator","jira.view.issue","jira.global","atl.general"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component"]}, + "410": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","project.issue.navigator","jira.view.issue","jira.global","atl.general"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component"]}, + "415": [{"name":"quicksearch.enabled","properties":{},"timeDelta":-1025},{"name":"jira.project.sidebar.issue.view.issue","properties":{"issueId":914565,"projectId":10448,"projectType":"software","issueMatchesProjectContext":true},"timeDelta":-902},{"name":"bigpipe.sidebar.render.success","properties":{},"timeDelta":-697},{"name":"issue.dnd.attachment.attachmentsdropzone.init","properties":{},"timeDelta":-690},{"name":"atst.healthcheck.sensors.page-protocols","properties":{"resourceProtocols":"http/1.1","navigationProtocol":"http/1.1","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36"},"timeDelta":-660},{"name":"jira.wikieditor.initialized","properties":{},"timeDelta":-660}], + "420": {"r":[],"c":["jira.rich.editor.api","jira.rich.editor","jira.project.sidebar","jira.project.sidebar.software","com.atlassian.jira.plugins.jira-development-integration-plugin:0"],"xc":["_super","project.issue.navigator","jira.view.issue","jira.global","atl.general","browser-metrics-plugin.contrib","atl.global","com.atlassian.jira.projects.sidebar.init","jira.global.look-and-feel"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:calendar-en","jira.webresources:calendar-localisation-moment","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init"]}, + "425": [{"name":"browser.metrics.navigation","properties":{"apdex":"0.5","firstPaint":"1285","isInitial":"true","journeyId":"68d353c0-5dc0-449b-a7ce-f348f8a8372b","key":"jira.project.issue.view-issue","navigationType":"1","readyForUser":"1993","redirectCount":"0","resourceLoadedEnd":"1029","resourceLoadedStart":294.43000000173924,"threshold":"1000","unloadEventStart":"188","unloadEventEnd":"190","fetchStart":"2","domainLookupStart":"2","domainLookupEnd":"2","connectStart":"2","connectEnd":"2","requestStart":"7","responseStart":"159","responseEnd":"239","domLoading":"224","domInteractive":"1793","domContentLoadedEventStart":"1793","domContentLoadedEventEnd":"2081","domComplete":"2995","loadEventStart":"2995","loadEventEnd":"3004","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36","correlationId":"6280673a8e3ab6","effectiveType":"4g","downlink":10,"rtt":100,"serverDuration":"103","dbReadsTimeInMs":"14","dbConnsTimeInMs":"29","applicationHash":"e00b0abe8f1b188f0bb304a4c3b424f1180ba767","resourceTiming":"{\"☠\":[\"2,86,d8,cf,8s,86,,86,86,86\",\"2,87,da,cd,8t,87,,87,87,87\",\"2,87,cc,cb,8t,87,,87,87,87\",\"3,88,gf,cj,8t,88,,88,88,88\",\"3,88,qz,cm,8u,88,,88,88,88\",\"3,89,db,ci,8u,89,,89,89,89\",\"3,89,h6,gz,dc,89,,89,89,89\",\"3,8a,h7,h3,dd,8a,,8a,8a,8a\",\"3,8a,jm,ji,fy,8a,,8a,8a,8a\",\"3,8a,kb,k7,gh,8a,,8a,8a,8a\",\"2,8b,fy,fw,cc,8b,,8b,8b,8b\",\"3,8b,kt,ks,h8,8b,,8b,8b,8b\",\"2,8c,h7,gv,da,8c,,8c,8c,8c\",\"3,8c,l0,ku,h9,8c,,8c,8c,8c\",\"3,9j,os,oo,l3,9j,,9j,9j,9j\",\"3,9j,sl,sj,oy,9j,,9j,9j,9j\",\"5,kj,o9,o7,km,kj,,kj,kj,kj\",\"5,ua,y7,y5,uh,ua,,ua,ua,ua\",\"4,yb,1dr,1dl,19p,yb,,yb,yb,yb\",\"4,10a,141,13y,10e,10a,,10a,10a,10a\"]}","mark.bigPipe.sidebar-id.start":"[1700]","mark.bigPipe.sidebar-id.end":"[1704]","mark.bigPipe.activity-panel-pipe-id.start":"[1705]","mark.bigPipe.activity-panel-pipe-id.end":"[1709]","userTimingRaw":"{\"marks\":{\"bigPipe.sidebar-id.start\":[1700],\"bigPipe.sidebar-id.end\":[1704],\"bigPipe.activity-panel-pipe-id.start\":[1705],\"bigPipe.activity-panel-pipe-id.end\":[1709]},\"measures\":{}}","experiments":"[]","serverHeadDuration":"undefined","connectionEffectiveType":"4g","connectionDownlink":10,"connectionRTT":100},"timeDelta":-5035},{"name":"jira.project.centric.navigation.sidebar.load.project","properties":{},"timeDelta":-4563}] }, - "edit_issue": { - "705": { - "r": [ - ], - "c": [ - "browser-metrics-plugin.contrib" - ], - "xc": [ - "_super", - "atl.general", - "jira.edit.issue", - "jira.general", - "jira.global" - ], - "xr": [ - "com.atlassian.auiplugin:aui-labels", - "jira.webresources:global-static-adgs", - "jira.webresources:global-static" - ] - }, - "710": { - "r": [ - ], - "c": [ - "jira.webresources:mentions-feature" - ], - "xc": [ - "_super", - "atl.general", - "jira.edit.issue", - "jira.general", - "jira.global", - "browser-metrics-plugin.contrib", - "atl.global", - "jira.global.look-and-feel" - ], - "xr": [ - "com.atlassian.auiplugin:aui-labels", - "jira.webresources:global-static-adgs", - "jira.webresources:global-static", - "com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component", - "com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib", - "jira.webresources:calendar-en", - "jira.webresources:calendar-localisation-moment", - "jira.webresources:bigpipe-js", - "jira.webresources:bigpipe-init" - ] - }, - "720": { - "r": [ - "com.atlassian.jira.jira-header-plugin:newsletter-signup-tip", - "com.atlassian.jira.plugins.jira-editor-plugin:api", - "com.atlassian.jira.plugins.jira-editor-plugin:resources", - "com.atlassian.jira.plugins.jira-editor-plugin:converter" - ], - "c": [ - "jira.rich.editor" - ], - "xc": [ - "_super", - "atl.general", - "jira.edit.issue", - "jira.general", - "jira.global", - "browser-metrics-plugin.contrib", - "atl.global", - "jira.global.look-and-feel" - ], - "xr": [ - "com.atlassian.auiplugin:aui-labels", - "jira.webresources:global-static-adgs", - "jira.webresources:global-static", - "com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component", - "com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib", - "jira.webresources:calendar-en", - "jira.webresources:calendar-localisation-moment", - "jira.webresources:bigpipe-js", - "jira.webresources:bigpipe-init" - ] - }, - "740": { - "r": [ - ], - "c": [ - "browser-metrics-plugin.contrib" - ], - "xc": [ - "_super", - "project.issue.navigator", - "jira.view.issue", - "jira.global", - "atl.general", - "jira.general" - ], - "xr": [ - ] - }, - "745": { - "r": [ - ], - "c": [ - "com.atlassian.jira.plugins.jira-development-integration-plugin:0" - ], - "xc": [ - "_super", - "project.issue.navigator", - "jira.view.issue", - "jira.global", - "atl.general", - "jira.general", - "browser-metrics-plugin.contrib", - "atl.global", - "com.atlassian.jira.projects.sidebar.init", - "jira.global.look-and-feel" - ], - "xr": [ - "com.atlassian.plugins.atlassian-chaperone:hotspot-tour", - "com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component", - "com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib", - "jira.webresources:calendar-en", - "jira.webresources:calendar-localisation-moment", - "jira.webresources:bigpipe-js", - "jira.webresources:bigpipe-init" - ] - }, - "765": { - "r": [ - "com.atlassian.jira.plugins.jira-editor-plugin:api", - "com.atlassian.jira.plugins.jira-editor-plugin:resources", - "com.atlassian.jira.plugins.jira-editor-plugin:converter", - "com.atlassian.jira.jira-header-plugin:newsletter-signup-tip" - ], - "c": [ - "jira.webresources:mentions-feature", - "jira.rich.editor" - ], - "xc": [ - "_super", - "project.issue.navigator", - "jira.view.issue", - "jira.global", - "atl.general", - "jira.general", - "browser-metrics-plugin.contrib", - "atl.global", - "com.atlassian.jira.projects.sidebar.init", - "jira.global.look-and-feel", - "com.atlassian.jira.plugins.jira-development-integration-plugin:0" - ], - "xr": [ - "com.atlassian.plugins.atlassian-chaperone:hotspot-tour", - "com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component", - "com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib", - "jira.webresources:calendar-en", - "jira.webresources:calendar-localisation-moment", - "jira.webresources:bigpipe-js", - "jira.webresources:bigpipe-init" - ] - }, - "775": { - "r": [ - ], - "c": [ - "jira.project.sidebar", - "jira.project.sidebar.software" - ], - "xc": [ - "_super", - "project.issue.navigator", - "jira.view.issue", - "jira.global", - "atl.general", - "jira.general", - "browser-metrics-plugin.contrib", - "atl.global", - "com.atlassian.jira.projects.sidebar.init", - "jira.global.look-and-feel", - "com.atlassian.jira.plugins.jira-development-integration-plugin:0", - "jira.rich.editor" - ], - "xr": [ - "com.atlassian.plugins.atlassian-chaperone:hotspot-tour", - "com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component", - "com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib", - "jira.webresources:calendar-en", - "jira.webresources:calendar-localisation-moment", - "jira.webresources:bigpipe-js", - "jira.webresources:bigpipe-init", - "com.atlassian.jira.jira-header-plugin:newsletter-signup-tip", - "com.atlassian.jira.plugins.jira-editor-plugin:tinymce", - "com.atlassian.jira.plugins.jira-editor-plugin:schema-builder", - "com.atlassian.jira.plugins.jira-editor-plugin:schema", - "com.atlassian.jira.plugins.jira-editor-plugin:i18n", - "com.atlassian.jira.plugins.jira-editor-plugin:wrm", - "com.atlassian.jira.plugins.jira-editor-plugin:converter-util", - "com.atlassian.jira.plugins.jira-editor-plugin:context-detector", - "com.atlassian.jira.plugins.jira-editor-plugin:context-manager", - "com.atlassian.jira.plugins.jira-editor-plugin:selection", - "com.atlassian.jira.plugins.jira-editor-plugin:instance", - "com.atlassian.jira.plugins.jira-editor-plugin:api", - "com.atlassian.jira.plugins.jira-editor-plugin:renderer", - "com.atlassian.jira.plugins.jira-editor-plugin:mentions", - "com.atlassian.jira.plugins.jira-editor-plugin:mentions-plugin", - "com.atlassian.jira.plugins.jira-editor-plugin:polyfil-string-ends-with", - "com.atlassian.jira.plugins.jira-editor-plugin:resources", - "com.atlassian.jira.plugins.jira-editor-plugin:converter", - "com.atlassian.plugin.jslibs:underscore-1.8.3" - ] - } + "view_project_summary": { + "505": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","com.atlassian.jira.project.summary.page","jira.project.sidebar","atl.general","jira.global","com.atlassian.jira.projects.sidebar.init"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","jira.webresources:calendar-lib","jira.webresources:autocomplete","jira.webresources:groupbrowser","jira.webresources:group-pickers"]}, + "510": {"r":[],"c":["jira.webresources:mentions-feature","jira.project.sidebar","jira.project.sidebar.software"],"xc":["_super","com.atlassian.jira.project.summary.page","jira.project.sidebar","atl.general","jira.global","com.atlassian.jira.projects.sidebar.init","browser-metrics-plugin.contrib","atl.global","jira.global.look-and-feel"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","jira.webresources:calendar-lib","jira.webresources:autocomplete","jira.webresources:groupbrowser","jira.webresources:group-pickers","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:calendar","jira.webresources:group-label-lozenge","jira.webresources:jira-project-issuetype-fields","jira.webresources:jira-fields","jira.webresources:calendar-en","jira.webresources:calendar-localisation-moment","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init"]}, + "515": [{"name":"quicksearch.enabled","properties":{},"timeDelta":-768},{"name":"jira.projects.summary.page.activity.stream.selected","properties":{},"timeDelta":-712},{"name":"bigpipe.sidebar.render.success","properties":{},"timeDelta":-504},{"name":"atst.healthcheck.sensors.page-protocols","properties":{"resourceProtocols":"http/1.1","navigationProtocol":"http/1.1","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36"},"timeDelta":-499}], + "520": [{"name":"jira.project.centric.navigation.sidebar.load.project","properties":{},"timeDelta":-5506}] }, "view_dashboard": { - "605": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","atl.dashboard","jira.global","atl.general","jira.general"],"xr":[]}, - "620": {"r":["com.atlassian.jira.jira-header-plugin:newsletter-signup-tip"],"c":["jira.webresources:mentions-feature","com.atlassian.jira.plugins.jira-development-integration-plugin:0"],"xc":["_super","atl.dashboard","jira.global","atl.general","jira.general","browser-metrics-plugin.contrib","atl.global","jira.dashboard","jira.global.look-and-feel"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:calendar-en","jira.webresources:calendar-localisation-moment","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init"]} - + "605": {"r":[],"c":["jira.webresources:mentions-feature"],"xc":["_super","atl.dashboard","jira.global","atl.general","jira.dashboard"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component"]}, + "610": {"r":[],"c":["browser-metrics-plugin.contrib","com.atlassian.jira.plugins.jira-development-integration-plugin:8"],"xc":["_super","atl.dashboard","jira.global","atl.general","jira.dashboard","atl.global","jira.global.look-and-feel"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:calendar-en","jira.webresources:calendar-localisation-moment"]}, + "625": {"r":[],"c":["com.atlassian.jira.plugins.jira-development-integration-plugin:0"],"xc":["_super","atl.dashboard","jira.global","atl.general","jira.dashboard","atl.global","jira.global.look-and-feel","com.atlassian.jira.plugins.jira-development-integration-plugin:8","browser-metrics-plugin.contrib"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:calendar-en","jira.webresources:calendar-localisation-moment","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init"]}, + "630": [{"name":"quicksearch.enabled","properties":{},"timeDelta":-1003}], + "635": [{"name":"browser.metrics.navigation","properties":{"apdex":"0","firstPaint":"2911","isInitial":"true","journeyId":"68d353c0-5dc0-449b-a7ce-f348f8a8372b","key":"jira.dashboard","navigationType":"0","readyForUser":"6462","redirectCount":"0","resourceLoadedEnd":"2443","resourceLoadedStart":404.9200000008568,"threshold":"1000","unloadEventStart":"298","unloadEventEnd":"299","fetchStart":"1","domainLookupStart":"5","domainLookupEnd":"5","connectStart":"5","connectEnd":"126","requestStart":"126","responseStart":"273","responseEnd":"399","domLoading":"323","domInteractive":"2919","domContentLoadedEventStart":"2920","domContentLoadedEventEnd":"3212","domComplete":"6484","loadEventStart":"6485","loadEventEnd":"6492","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36","correlationId":"7df18fb2e75e61","effectiveType":"4g","downlink":3.95,"rtt":100,"serverDuration":"39","dbConnsTimeInMs":"7","applicationHash":"e00b0abe8f1b188f0bb304a4c3b424f1180ba767","resourceTiming":"{\"☠\":[\"2,b8,it,fb,bm,b8,,b8,b8,b8\",\"2,ba,y3,fq,bx,ba,,ba,ba,ba\",\"2,bc,j0,iy,fh,fh,,by,by,by\",\"3,bd,1it,jn,fv,fq,,c7,c7,c7\",\"3,bd,1tc,jp,fv,fu,,c5,c5,c5\",\"3,be,mf,md,iv,be,,be,be,be\",\"3,be,rc,qd,j0,be,,be,be,be\",\"3,bf,nt,nn,jy,bf,,bf,bf,bf\",\"3,bf,r2,qi,mg,bf,,bf,bf,bf\",\"3,bf,ri,rf,nw,bf,,bf,bf,bf\",\"2,bg,jt,jl,fu,fq,,c7,c7,c7\",\"3,bg,v8,v5,ra,bg,,bg,bg,bg\",\"3,bi,1ng,1ne,1jy,bi,,bi,bi,bi\",\"3,bi,1vv,1vu,1sd,bi,,bi,bi,bi\",\"5,1s4,1w3,1w1,1sd,1s4,,1s4,1s4,1s4\",\"4,235,2bj,2bg,27v,235,,235,235,235\",\"5,27b,2bu,2bs,27v,27b,,27b,27b,27b\",\"5,2ec,2j7,2iz,2eo,2ec,,2ec,2ec,2ec\",\"-1,2fw,2kj,2k1,2g7,2fw,,2fw,2fw,2fw\",\"5,2gg,2ki,2kb,2gk,2gg,,2gg,2gg,2gg\",\"2,2iv,2n1,2my,2jc,2iv,,2iv,2iv,2iv\",\"3,2iy,2od,2o5,2km,2iy,,2iy,2iy,2iy\",\"3,2j0,2oc,2o9,2kn,2j0,,2j0,2j0,2j0\",\"5,2yt,36h,36d,2zi,2yt,,2yt,2yt,2yt\",\"5,32x,4ek,4ei,4ap,32x,,32x,32x,32x\",\"2,36v,3j4,3ii,3ew,36v,,36v,36v,36v\",\"3,36z,4so,4p3,4lj,36z,,36z,36z,36z\"]}","userTimingRaw":"{\"marks\":{},\"measures\":{}}","experiments":"[]","dbReadsTimeInMs":"","serverHeadDuration":"undefined","connectionEffectiveType":"4g","connectionDownlink":3.95,"connectionRTT":100},"timeDelta":-3952}] + }, + "edit_issue": { + "705": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","atl.general","jira.global","jira.edit.issue"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component"]}, + "710": {"r":[],"c":["jira.webresources:mentions-feature","jira.rich.editor.api","jira.rich.editor"],"xc":["_super","atl.general","jira.global","jira.edit.issue","browser-metrics-plugin.contrib","atl.global","jira.global.look-and-feel"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:calendar-en","jira.webresources:calendar-localisation-moment","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init"]}, + "715": [{"name":"quicksearch.enabled","properties":{},"timeDelta":-1399},{"name":"jira.wikieditor.initialized","properties":{},"timeDelta":-1335},{"name":"jira.wikieditor.initialized","properties":{},"timeDelta":-1190},{"name":"jira.wikieditor.initialized","properties":{},"timeDelta":-1070},{"name":"jira.wikieditor.initialized","properties":{},"timeDelta":-953},{"name":"issue.dnd.attachment.createissuedropzone.init","properties":{},"timeDelta":-493},{"name":"atst.healthcheck.sensors.page-protocols","properties":{"resourceProtocols":"http/1.1","navigationProtocol":"http/1.1","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36"},"timeDelta":-455}], + "720": [{"name":"editor.instance.init","properties":{},"timeDelta":-4341},{"name":"bundled.editor.instance.init","properties":{},"timeDelta":-4341},{"name":"editor.instance.init.chrome","properties":{},"timeDelta":-4341},{"name":"editor.instance.init","properties":{},"timeDelta":-4300},{"name":"bundled.editor.instance.init","properties":{},"timeDelta":-4300},{"name":"editor.instance.init.chrome","properties":{},"timeDelta":-4300},{"name":"editor.instance.init","properties":{},"timeDelta":-4279},{"name":"bundled.editor.instance.init","properties":{},"timeDelta":-4279},{"name":"editor.instance.init.chrome","properties":{},"timeDelta":-4279},{"name":"editor.instance.init","properties":{},"timeDelta":-4263},{"name":"bundled.editor.instance.init","properties":{},"timeDelta":-4263},{"name":"editor.instance.init.chrome","properties":{},"timeDelta":-4263},{"name":"editor.instance.perf.nodechange","properties":{"time":6.994999999733409},"timeDelta":-3873},{"name":"editor.instance.perf.init","properties":{"time":2261.2850000004983},"timeDelta":-3840},{"name":"editor.instance.init.perf","properties":{"time":43.92999999981839},"timeDelta":-3840},{"name":"editor.instance.perf.init-bare","properties":{"time":2261.545000001206},"timeDelta":-3840},{"name":"editor.instance.perf.nodechange","properties":{"time":3.1249999992724042},"timeDelta":-3823},{"name":"editor.instance.perf.nodechange","properties":{"time":2.669999998033745},"timeDelta":-3816},{"name":"editor.instance.perf.nodechange","properties":{"time":3.8499999973282684},"timeDelta":-3796},{"name":"editor.instance.perf.init","properties":{"time":2313.545000000886},"timeDelta":-3788},{"name":"editor.instance.init.perf","properties":{"time":13.74999999825377},"timeDelta":-3788},{"name":"editor.instance.perf.init-bare","properties":{"time":2313.6799999992945},"timeDelta":-3788},{"name":"editor.instance.perf.nodechange","properties":{"time":1.874999998108251},"timeDelta":-3768},{"name":"editor.instance.perf.nodechange","properties":{"time":4.114999999728752},"timeDelta":-3761},{"name":"editor.instance.perf.nodechange","properties":{"time":6.1700000005657785},"timeDelta":-3735},{"name":"editor.instance.perf.init","properties":{"time":2386.3649999984773},"timeDelta":-3715},{"name":"editor.instance.init.perf","properties":{"time":27.78500000204076},"timeDelta":-3715},{"name":"editor.instance.perf.init-bare","properties":{"time":2386.5399999995134},"timeDelta":-3715},{"name":"editor.instance.perf.nodechange","properties":{"time":2.675000003364403},"timeDelta":-3700},{"name":"editor.instance.perf.nodechange","properties":{"time":5.284999999275897},"timeDelta":-3679},{"name":"editor.instance.perf.nodechange","properties":{"time":15.005000001110602},"timeDelta":-3652},{"name":"editor.instance.perf.init","properties":{"time":2462.8149999989546},"timeDelta":-3639},{"name":"editor.instance.init.perf","properties":{"time":30.36499999871012},"timeDelta":-3638},{"name":"editor.instance.perf.init-bare","properties":{"time":2462.9600000007486},"timeDelta":-3638},{"name":"editor.instance.perf.nodechange","properties":{"time":1.5500000008614734},"timeDelta":-3625},{"name":"editor.instance.perf.nodechange","properties":{"time":1.7299999999522697},"timeDelta":-3621}], + "735": {"r":[],"c":["jira.webresources:mentions-feature"],"xc":["_super","project.issue.navigator","jira.view.issue","jira.global","atl.general"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component"]}, + "740": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","project.issue.navigator","jira.view.issue","jira.global","atl.general"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component"]}, + "755": [{"name":"quicksearch.enabled","properties":{},"timeDelta":-994},{"name":"jira.project.sidebar.issue.view.issue","properties":{"issueId":914565,"projectId":10448,"projectType":"software","issueMatchesProjectContext":true},"timeDelta":-825},{"name":"bigpipe.sidebar.render.success","properties":{},"timeDelta":-646},{"name":"issue.dnd.attachment.attachmentsdropzone.init","properties":{},"timeDelta":-640},{"name":"jira.wikieditor.initialized","properties":{},"timeDelta":-617}], + "760": {"r":[],"c":["jira.rich.editor.api","jira.rich.editor","jira.project.sidebar","jira.project.sidebar.software","com.atlassian.jira.plugins.jira-development-integration-plugin:0"],"xc":["_super","project.issue.navigator","jira.view.issue","jira.global","atl.general","browser-metrics-plugin.contrib","atl.global","com.atlassian.jira.projects.sidebar.init","jira.global.look-and-feel"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:calendar-en","jira.webresources:calendar-localisation-moment","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init"]}, + "770": [{"name":"browser.metrics.navigation","properties":{"apdex":"0.5","firstPaint":"2289","isInitial":"true","journeyId":"68d353c0-5dc0-449b-a7ce-f348f8a8372b","key":"jira.project.issue.view-issue","navigationType":"0","readyForUser":"3249","redirectCount":"1","resourceLoadedEnd":"1925","resourceLoadedStart":640.8699999992677,"threshold":"1000","unloadEventStart":"539","unloadEventEnd":"540","redirectStart":"91","redirectEnd":"350","fetchStart":"350","domainLookupStart":"350","domainLookupEnd":"350","connectStart":"350","connectEnd":"350","requestStart":"353","responseStart":"500","responseEnd":"597","domLoading":"605","domInteractive":"2884","domContentLoadedEventStart":"2884","domContentLoadedEventEnd":"3312","domComplete":"4483","loadEventStart":"4484","loadEventEnd":"4499","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36","correlationId":"bcd0e1be057334","effectiveType":"4g","downlink":5.6,"rtt":100,"serverDuration":"115","dbReadsTimeInMs":"18","dbConnsTimeInMs":"32","applicationHash":"e00b0abe8f1b188f0bb304a4c3b424f1180ba767","resourceTiming":"{\"☠\":[\"2,hs,pl,lv,hw,hs,,hs,hs,hs\",\"2,ht,sy,ll,hz,ht,,ht,ht,ht\",\"2,ht,lk,lg,hz,ht,,ht,ht,ht\",\"3,hu,10w,ln,i0,hu,,hu,hu,hu\",\"3,hu,1hh,lo,i0,hu,,hu,hu,hu\",\"3,hu,lx,lr,i0,hu,,hu,hu,hu\",\"3,hv,ta,t2,pf,hv,,hv,hv,hv\",\"3,hv,th,te,pt,hv,,hv,hv,hv\",\"3,hw,tr,th,pw,hw,,hw,hw,hw\",\"3,hw,x8,wr,t1,hw,,hw,hw,hw\",\"2,hw,pd,p8,lk,hw,,hw,hw,hw\",\"3,hx,x6,wx,tb,hx,,hx,hx,hx\",\"2,hx,pt,pn,m0,hx,,hx,hx,hx\",\"3,hx,xn,xd,tq,hx,,hx,hx,hx\",\"3,kl,157,155,11o,kl,,kl,kl,kl\",\"3,km,1dw,1dp,1a6,km,,km,km,km\",\"5,1a2,1dx,1ds,1a5,1a2,,1a2,1a2,1a2\",\"5,1my,1qp,1qn,1n1,1my,,1my,1my,1my\",\"4,1px,249,246,20l,1px,,1px,1px,1px\",\"4,1ys,22v,22t,1yu,1ys,,1ys,1ys,1ys\"]}","mark.bigPipe.sidebar-id.start":"[2762]","mark.bigPipe.sidebar-id.end":"[2764]","mark.bigPipe.activity-panel-pipe-id.start":"[2765]","mark.bigPipe.activity-panel-pipe-id.end":"[2773]","userTimingRaw":"{\"marks\":{\"bigPipe.sidebar-id.start\":[2762],\"bigPipe.sidebar-id.end\":[2764],\"bigPipe.activity-panel-pipe-id.start\":[2765],\"bigPipe.activity-panel-pipe-id.end\":[2773]},\"measures\":{}}","experiments":"[]","serverHeadDuration":"undefined","connectionEffectiveType":"4g","connectionDownlink":5.6,"connectionRTT":100},"timeDelta":-4643},{"name":"jira.project.centric.navigation.sidebar.load.project","properties":{},"timeDelta":-4321}] }, "add_comment": { - "805": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","atl.general","jira.edit.issue","jira.general","jira.global"],"xr":["com.atlassian.auiplugin:aui-labels","jira.webresources:global-static-adgs","jira.webresources:global-static"]}, - "810": {"r":[],"c":["jira.webresources:mentions-feature"],"xc":["_super","atl.general","jira.edit.issue","jira.general","jira.global","browser-metrics-plugin.contrib","atl.global","jira.global.look-and-feel"],"xr":["com.atlassian.auiplugin:aui-labels","jira.webresources:global-static-adgs","jira.webresources:global-static","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init"]}, - "820": {"r":["com.atlassian.jira.jira-header-plugin:newsletter-signup-tip","com.atlassian.jira.plugins.jira-editor-plugin:api","com.atlassian.jira.plugins.jira-editor-plugin:resources","com.atlassian.jira.plugins.jira-editor-plugin:converter"],"c":["jira.rich.editor"],"xc":["_super","atl.general","jira.edit.issue","jira.general","jira.global","browser-metrics-plugin.contrib","atl.global","jira.global.look-and-feel"],"xr":["com.atlassian.auiplugin:aui-labels","jira.webresources:global-static-adgs","jira.webresources:global-static","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init"]} + "805": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","atl.general","jira.global","jira.edit.issue"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component"]}, + "810": {"r":[],"c":["jira.webresources:mentions-feature","jira.rich.editor.api","jira.rich.editor"],"xc":["_super","atl.general","jira.global","jira.edit.issue","browser-metrics-plugin.contrib","atl.global","jira.global.look-and-feel"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init"]}, + "815": [{"name":"quicksearch.enabled","properties":{},"timeDelta":-862},{"name":"jira.wikieditor.initialized","properties":{},"timeDelta":-817},{"name":"issue.dnd.attachment.createissuedropzone.init","properties":{},"timeDelta":-493}], + "825": [{"name":"editor.instance.init","properties":{},"timeDelta":-4782},{"name":"bundled.editor.instance.init","properties":{},"timeDelta":-4781},{"name":"editor.instance.init.chrome","properties":{},"timeDelta":-4781},{"name":"editor.instance.perf.nodechange","properties":{"time":6.580000001122244},"timeDelta":-4290},{"name":"editor.instance.perf.init","properties":{"time":1666.175000005751},"timeDelta":-4253},{"name":"editor.instance.init.perf","properties":{"time":47.44500000379048},"timeDelta":-4253},{"name":"editor.instance.perf.init-bare","properties":{"time":1666.5150000044378},"timeDelta":-4253},{"name":"editor.instance.perf.nodechange","properties":{"time":2.3499999952036887},"timeDelta":-4230},{"name":"editor.instance.perf.nodechange","properties":{"time":1.6399999876739457},"timeDelta":-4224},{"name":"editor.instance.perf.nodechange","properties":{"time":1.6899999900488183},"timeDelta":-4134},{"name":"editor.instance.perf.nodechange","properties":{"time":2.2250000038184226},"timeDelta":-4128}], + "845": [{"name":"editor.instance.perf.nodechange","properties":{"time":1.8149999959859997},"timeDelta":-3280},{"name":"editor.instance.perf.nodechange","properties":{"time":0.910000002477318},"timeDelta":-3160},{"name":"editor.instance.perf.convert","properties":{"nodesCount":1,"time":5.629999999655411},"timeDelta":-2592},{"name":"editor.instance.perf.nodechange","properties":{"time":1.360000009299256},"timeDelta":-2587},{"name":"editor.instance.perf.convert","properties":{"nodesCount":1,"time":2.545000010286458},"timeDelta":-813},{"name":"editor.instance.perf.nodechange","properties":{"time":1.7099999968195334},"timeDelta":-390}], + "860": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","project.issue.navigator","jira.view.issue","jira.global","atl.general"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component"]}, + "875": {"r":[],"c":["jira.webresources:mentions-feature","jira.rich.editor.api","jira.rich.editor","jira.project.sidebar","jira.project.sidebar.software","com.atlassian.jira.plugins.jira-development-integration-plugin:0"],"xc":["_super","project.issue.navigator","jira.view.issue","jira.global","atl.general","browser-metrics-plugin.contrib","atl.global","com.atlassian.jira.projects.sidebar.init","jira.global.look-and-feel"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:calendar-en","jira.webresources:calendar-localisation-moment","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init"]}, + "880": [{"name":"jira.project.sidebar.issue.view.issue","properties":{"issueId":914565,"projectId":10448,"projectType":"software","issueMatchesProjectContext":true},"timeDelta":-1978},{"name":"jira.wikieditor.initialized","properties":{},"timeDelta":-1497},{"name":"quicksearch.enabled","properties":{},"timeDelta":-1063},{"name":"bigpipe.sidebar.render.success","properties":{},"timeDelta":-650},{"name":"issue.dnd.attachment.attachmentsdropzone.init","properties":{},"timeDelta":-639}] }, "browse_projects": { - "905": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","atl.general","jira.general","jira.global"],"xr":["jira.webresources:calendar-lib","jira.webresources:autocomplete","jira.webresources:groupbrowser","jira.webresources:group-pickers","com.atlassian.auiplugin:aui-labels","jira.webresources:global-static-adgs","jira.webresources:global-static"]}, - "910": {"r":[],"c":["jira.webresources:mentions-feature"],"xc":["_super","atl.general","jira.general","jira.global","browser-metrics-plugin.contrib","atl.global","jira.global.look-and-feel"],"xr":["jira.webresources:calendar-lib","jira.webresources:autocomplete","jira.webresources:groupbrowser","jira.webresources:group-pickers","com.atlassian.auiplugin:aui-labels","jira.webresources:global-static-adgs","jira.webresources:global-static","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","com.atlassian.plugin.jslibs:backbone.paginator-2.0.2-factory","jira.webresources:backbone-paginator","jira.webresources:backbone-queryparams","jira.webresources:project-type-keys","com.atlassian.plugin.jslibs:marionette-1.6.1-factory","jira.webresources:marionette","jira.webresources:navigation-utils","jira.webresources:pagination-view","jira.webresources:browseprojects","jira.webresources:calendar","jira.webresources:group-label-lozenge","jira.webresources:ie-imitation-placeholder","jira.webresources:jira-project-issuetype-fields","jira.webresources:jira-fields","jira.webresources:calendar-en","jira.webresources:calendar-localisation-moment","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init"]}, - "920": {"r":["com.atlassian.jira.jira-header-plugin:newsletter-signup-tip"],"c":[],"xc":["_super","atl.general","jira.general","jira.global","browser-metrics-plugin.contrib","atl.global","jira.global.look-and-feel"],"xr":["jira.webresources:calendar-lib","jira.webresources:autocomplete","jira.webresources:groupbrowser","jira.webresources:group-pickers","com.atlassian.auiplugin:aui-labels","jira.webresources:global-static-adgs","jira.webresources:global-static","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","com.atlassian.plugin.jslibs:backbone.paginator-2.0.2-factory","jira.webresources:backbone-paginator","jira.webresources:backbone-queryparams","jira.webresources:project-type-keys","com.atlassian.plugin.jslibs:marionette-1.6.1-factory","jira.webresources:marionette","jira.webresources:navigation-utils","jira.webresources:pagination-view","jira.webresources:browseprojects","jira.webresources:calendar","jira.webresources:group-label-lozenge","jira.webresources:ie-imitation-placeholder","jira.webresources:jira-project-issuetype-fields","jira.webresources:jira-fields","jira.webresources:calendar-en","jira.webresources:calendar-localisation-moment","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init"]} + "905": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","atl.general","jira.global"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","jira.webresources:calendar-lib","jira.webresources:autocomplete","jira.webresources:groupbrowser","jira.webresources:group-pickers"]}, + "910": {"r":[],"c":["jira.webresources:mentions-feature"],"xc":["_super","atl.general","jira.global","browser-metrics-plugin.contrib","atl.global","jira.global.look-and-feel"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","jira.webresources:calendar-lib","jira.webresources:autocomplete","jira.webresources:groupbrowser","jira.webresources:group-pickers","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","com.atlassian.plugin.jslibs:underscore-1.8.3","com.atlassian.plugin.jslibs:backbone-1.3.3-factory","jira.webresources:backbone-1.3.3","com.atlassian.plugin.jslibs:backbone.paginator-2.0.2-factory","jira.webresources:backbone-paginator","com.atlassian.plugin.jslibs:backbone.radio-2.0.0-factory","jira.webresources:backbone.radio-2.0","com.atlassian.plugin.jslibs:marionette-4.1.2-factory","jira.webresources:marionette-4.1","com.atlassian.plugin.jslibs:marionette-1.6.1-factory","jira.webresources:marionette","jira.webresources:project-type-keys","com.atlassian.plugin.jslibs:marionette-3.1.0-factory","jira.webresources:marionette-3.1","jira.webresources:pagination-view","jira.webresources:navigation-utils","jira.webresources:empty-search-results","jira.webresources:browseprojects","jira.webresources:calendar","jira.webresources:group-label-lozenge","jira.webresources:jira-project-issuetype-fields","jira.webresources:jira-fields","jira.webresources:calendar-en","jira.webresources:calendar-localisation-moment","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init"]}, + "915": [{"name":"quicksearch.enabled","properties":{},"timeDelta":-955},{"name":"projects.browse.view","properties":{},"timeDelta":-940}] }, "view_kanban_board": { - "1000": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","gh-rapid-exception","greenhopper-rapid-non-gadget","atl.general","gh-rapid","jira.project.sidebar","com.atlassian.jira.projects.sidebar.init","jira.global","jira.general","gh-rapid-charts"],"xr":[]}, - "1005": {"r":[],"c":["com.pyxis.greenhopper.jira:gh-rapid-inline-editable"],"xc":["_super","gh-rapid-exception","greenhopper-rapid-non-gadget","atl.general","gh-rapid","jira.project.sidebar","com.atlassian.jira.projects.sidebar.init","jira.global","jira.general","gh-rapid-charts","browser-metrics-plugin.contrib","atl.global","jira.global.look-and-feel"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:calendar-en","jira.webresources:calendar-localisation-moment"]}, - "1010": {"r":[],"c":["com.atlassian.jira.plugins.jira-development-integration-plugin:0"],"xc":["_super","gh-rapid-exception","greenhopper-rapid-non-gadget","atl.general","gh-rapid","jira.project.sidebar","com.atlassian.jira.projects.sidebar.init","jira.global","jira.general","gh-rapid-charts","browser-metrics-plugin.contrib","atl.global","jira.global.look-and-feel","com.pyxis.greenhopper.jira:gh-rapid-inline-editable"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:calendar-en","jira.webresources:calendar-localisation-moment","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init"]}, - "1015": {"r":[],"c":["jira.webresources:mentions-feature"],"xc":["_super","gh-rapid-exception","greenhopper-rapid-non-gadget","atl.general","gh-rapid","jira.project.sidebar","com.atlassian.jira.projects.sidebar.init","jira.global","jira.general","gh-rapid-charts","browser-metrics-plugin.contrib","atl.global","jira.global.look-and-feel","com.pyxis.greenhopper.jira:gh-rapid-inline-editable","com.atlassian.jira.plugins.jira-development-integration-plugin:0"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:calendar-en","jira.webresources:calendar-localisation-moment","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init"]}, - "1020": {"r":["com.atlassian.jira.jira-header-plugin:newsletter-signup-tip"],"c":[],"xc":["_super","gh-rapid-exception","greenhopper-rapid-non-gadget","atl.general","gh-rapid","jira.project.sidebar","com.atlassian.jira.projects.sidebar.init","jira.global","jira.general","gh-rapid-charts","browser-metrics-plugin.contrib","atl.global","jira.global.look-and-feel","com.pyxis.greenhopper.jira:gh-rapid-inline-editable","com.atlassian.jira.plugins.jira-development-integration-plugin:0"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:calendar-en","jira.webresources:calendar-localisation-moment","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init"]}, - "1025": {"r":["com.atlassian.jira.plugins.jira-editor-plugin:api","com.atlassian.jira.plugins.jira-editor-plugin:resources","com.atlassian.jira.plugins.jira-editor-plugin:converter"],"c":["jira.rich.editor"],"xc":["_super","gh-rapid-exception","greenhopper-rapid-non-gadget","atl.general","gh-rapid","jira.project.sidebar","com.atlassian.jira.projects.sidebar.init","jira.global","jira.general","gh-rapid-charts","browser-metrics-plugin.contrib","atl.global","jira.global.look-and-feel","com.pyxis.greenhopper.jira:gh-rapid-inline-editable","com.atlassian.jira.plugins.jira-development-integration-plugin:0"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:calendar-en","jira.webresources:calendar-localisation-moment","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init","com.atlassian.jira.jira-header-plugin:newsletter-signup-tip","com.atlassian.plugin.jslibs:underscore-1.8.3"]}, - "1030": {"r":[],"c":["jira.project.sidebar","jira.project.sidebar.software"],"xc":["_super","gh-rapid-exception","greenhopper-rapid-non-gadget","atl.general","gh-rapid","jira.project.sidebar","com.atlassian.jira.projects.sidebar.init","jira.global","jira.general","gh-rapid-charts","browser-metrics-plugin.contrib","atl.global","jira.global.look-and-feel","com.pyxis.greenhopper.jira:gh-rapid-inline-editable","com.atlassian.jira.plugins.jira-development-integration-plugin:0","jira.rich.editor"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:calendar-en","jira.webresources:calendar-localisation-moment","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init","com.atlassian.jira.jira-header-plugin:newsletter-signup-tip","com.atlassian.plugin.jslibs:underscore-1.8.3","com.atlassian.jira.plugins.jira-editor-plugin:tinymce","com.atlassian.jira.plugins.jira-editor-plugin:schema-builder","com.atlassian.jira.plugins.jira-editor-plugin:schema","com.atlassian.jira.plugins.jira-editor-plugin:i18n","com.atlassian.jira.plugins.jira-editor-plugin:wrm","com.atlassian.jira.plugins.jira-editor-plugin:converter-util","com.atlassian.jira.plugins.jira-editor-plugin:context-detector","com.atlassian.jira.plugins.jira-editor-plugin:context-manager","com.atlassian.jira.plugins.jira-editor-plugin:selection","com.atlassian.jira.plugins.jira-editor-plugin:instance","com.atlassian.jira.plugins.jira-editor-plugin:api","com.atlassian.jira.plugins.jira-editor-plugin:renderer","com.atlassian.jira.plugins.jira-editor-plugin:mentions","com.atlassian.jira.plugins.jira-editor-plugin:mentions-plugin","com.atlassian.jira.plugins.jira-editor-plugin:polyfil-string-ends-with","com.atlassian.jira.plugins.jira-editor-plugin:resources","com.atlassian.jira.plugins.jira-editor-plugin:converter"]} + "1005": {"r":[],"c":["com.atlassian.jira.plugins.jira-development-integration-plugin:8"],"xc":["_super","gh-rapid-work","jira.project.sidebar","atl.general","jira.global","com.atlassian.jira.projects.sidebar.init","greenhopper-rapid-non-gadget","gh-rapid-charts"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component"]}, + "1015": {"r":["com.atlassian.whisper.atlassian-whisper-plugin:atlassian-whisper-hermes"],"c":["browser-metrics-plugin.contrib","jira.webresources:mentions-feature","jira.project.sidebar","jira.project.sidebar.software"],"xc":["_super","gh-rapid-work","jira.project.sidebar","atl.general","jira.global","com.atlassian.jira.projects.sidebar.init","greenhopper-rapid-non-gadget","gh-rapid-charts","com.atlassian.jira.plugins.jira-development-integration-plugin:8","gh-rapid-exception","atl.global","jira.global.look-and-feel"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:calendar-localisation-moment","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init"]}, + "1025": [{"name":"quicksearch.enabled","properties":{},"timeDelta":-646},{"name":"bigpipe.sidebar.render.success","properties":{},"timeDelta":-502},{"name":"RapidBoard.show","timeDelta":-442}], + "1040": {"r":[],"c":["gh-rapid-work"],"xc":["_super","gh-rapid-work","jira.project.sidebar","atl.general","jira.global","com.atlassian.jira.projects.sidebar.init","greenhopper-rapid-non-gadget","gh-rapid-charts","com.atlassian.jira.plugins.jira-development-integration-plugin:8","gh-rapid-exception","atl.global","jira.global.look-and-feel","browser-metrics-plugin.contrib"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:calendar-localisation-moment","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init","com.atlassian.auiplugin:split_aui.component.message","com.atlassian.plugin.jslibs:moment-2.6.0","com.atlassian.whisper.atlassian-whisper-plugin:atlassian-whisper-messages","com.atlassian.whisper.atlassian-whisper-plugin:atlassian-whisper-hermes"]}, + "1060": [{"name":"RapidBoard.show.kanban","properties":{"boardId":15},"timeDelta":-5067},{"name":"jira.project.centric.navigation.sidebar.load.project","properties":{},"timeDelta":-4750},{"name":"whisper.hermes.messages.load.success","properties":{"messageCount":1,"userLocale":"en_US","userLanguage":"en","invalidLanguageCount":0,"initTime":3168,"initState":"complete"},"timeDelta":-4633},{"name":"jira.project.sidebar.sprint.select","properties":{"sprintId":0,"initialLoad":true},"timeDelta":-4222},{"name":"jira-software.kanban.work.view","properties":{"boardId":15,"issuesCount":219,"isBacklogEnabled":false,"epicsPanelEnabled":true,"firstColumnIssueCount":219,"fastKanbanEnabled":true,"fastKanbanCutoff":"-2w","epicsCount":36},"timeDelta":-4057},{"name":"browser.metrics.navigation","properties":{"apdex":"0.5","firstPaint":"1878","isInitial":"true","journeyId":"68d353c0-5dc0-449b-a7ce-f348f8a8372b","key":"jira.agile.work","navigationType":"0","readyForUser":"3805","redirectCount":"0","resourceLoadedEnd":"1670","resourceLoadedStart":403.6950000008801,"threshold":"1000","unloadEventStart":"354","unloadEventEnd":"354","fetchStart":"2","domainLookupStart":"46","domainLookupEnd":"47","connectStart":"47","connectEnd":"170","requestStart":"171","responseStart":"347","responseEnd":"471","domLoading":"363","domInteractive":"1965","domContentLoadedEventStart":"1965","domContentLoadedEventEnd":"2074","domComplete":"2413","loadEventStart":"2414","loadEventEnd":"2419","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36","correlationId":"ae4d2d5aebb38b","effectiveType":"4g","downlink":4.65,"rtt":150,"serverDuration":"69","dbReadsTimeInMs":"1","dbConnsTimeInMs":"28","applicationHash":"e00b0abe8f1b188f0bb304a4c3b424f1180ba767","resourceTiming":"{\"☠\":[\"2,b7,iu,f6,bj,b7,,b7,b7,b7\",\"2,b8,qu,gu,d4,b8,,b8,b8,b8\",\"2,b8,jy,ji,fk,fk,,c4,c4,c4\",\"2,b8,k1,js,fn,fm,,c2,c2,c2\",\"3,b9,11x,jm,fo,fo,,c5,c5,c5\",\"3,b9,121,np,iv,b9,,b9,b9,b9\",\"3,ba,om,o9,k7,ba,,ba,ba,ba\",\"3,ba,oj,o1,k9,ba,,ba,ba,ba\",\"3,bd,ol,o5,ka,bd,,bd,bd,bd\",\"3,be,tc,sz,ot,be,,be,be,be\",\"3,bf,td,t4,ov,bf,,bf,bf,bf\",\"2,bf,jw,jf,fo,fm,,c3,c3,c3\",\"3,bf,te,t9,ov,bf,,bf,bf,bf\",\"3,bg,163,162,12k,bg,,bg,bg,bg\",\"3,ej,1ae,1ac,16b,ej,,ej,ej,ej\",\"5,17q,1bv,1bt,17w,17q,,17q,17q,17q\",\"4,1eo,1k4,1k1,1gh,1eo,,1eo,1eo,1eo\",\"5,1ke,1oq,1om,1kl,1ke,,1ke,1ke,1ke\",\"2,1me,1qp,1ql,1mq,1me,,1me,1me,1me\",\"3,1mh,1qn,1qf,1mr,1mh,,1mh,1mh,1mh\",\"5,1rb,1vm,1vl,1rh,1rb,,1rb,1rb,1rb\",\"3,1vp,1zs,1zo,1w2,1vp,,1vp,1vp,1vp\",\"3,1vq,203,1zz,1w9,1vq,,1vq,1vq,1vq\",\"3,1vt,207,200,1wc,1vt,,1vt,1vt,1vt\",\"3,1vw,203,1zv,1wd,1vw,,1vw,1vw,1vw\",\"3,1w1,2am,204,1wg,1w1,,1w1,1w1,1w1\",\"5,1yr,22x,22q,1yu,1yr,,1yr,1yr,1yr\",\"5,221,25p,25n,226,221,,221,221,221\",\"5,23y,28n,28i,24v,23y,,23y,23y,23y\",\"5,2cw,2gu,2gr,2d2,2cw,,2cw,2cw,2cw\",\"5,2cy,2hb,2h6,2d3,2cy,,2cy,2cy,2cy\",\"5,2jl,2ng,2nf,2jv,2jl,,2jl,2jl,2jl\",\"5,2kx,2q9,2q4,2l1,2kx,,2kx,2kx,2kx\"]}","mark.bigPipe.sidebar-id.start":"[1930]","mark.bigPipe.sidebar-id.end":"[1935]","userTimingRaw":"{\"marks\":{\"bigPipe.sidebar-id.start\":[1930],\"bigPipe.sidebar-id.end\":[1935]},\"measures\":{}}","experiments":"[]","serverHeadDuration":"undefined","connectionEffectiveType":"4g","connectionDownlink":4.65,"connectionRTT":150},"timeDelta":-3990}] + }, + "view_scrum_board": { + "1110": {"r":[],"c":["jira.webresources:mentions-feature"],"xc":["_super","gh-rapid-work","jira.project.sidebar","atl.general","jira.global","com.atlassian.jira.projects.sidebar.init","greenhopper-rapid-non-gadget","gh-rapid-charts"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component"]}, + "1115": {"r":[],"c":["com.atlassian.jira.plugins.jira-development-integration-plugin:8"],"xc":["_super","gh-rapid-work","jira.project.sidebar","atl.general","jira.global","com.atlassian.jira.projects.sidebar.init","greenhopper-rapid-non-gadget","gh-rapid-charts"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component"]}, + "1150": {"r":["com.atlassian.jira.plugins.jira-editor-plugin:api","com.atlassian.jira.plugins.jira-editor-plugin:resources","com.atlassian.jira.plugins.jira-editor-plugin:converter"],"c":["jira.rich.editor"],"xc":["_super","gh-rapid-exception","greenhopper-rapid-non-gadget","atl.general","gh-rapid","jira.project.sidebar","com.atlassian.jira.projects.sidebar.init","jira.global","jira.general","gh-rapid-charts","browser-metrics-plugin.contrib","atl.global","jira.global.look-and-feel","com.pyxis.greenhopper.jira:gh-rapid-inline-editable","com.atlassian.jira.plugins.jira-development-integration-plugin:0"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:calendar-en","jira.webresources:calendar-localisation-moment","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init","com.atlassian.jira.jira-header-plugin:newsletter-signup-tip","com.atlassian.plugin.jslibs:underscore-1.8.3"]}, + "1155": {"r":[],"c":["jira.project.sidebar","jira.project.sidebar.software"],"xc":["_super","gh-rapid-exception","greenhopper-rapid-non-gadget","atl.general","gh-rapid","jira.project.sidebar","com.atlassian.jira.projects.sidebar.init","jira.global","jira.general","gh-rapid-charts","browser-metrics-plugin.contrib","atl.global","jira.global.look-and-feel","com.pyxis.greenhopper.jira:gh-rapid-inline-editable","com.atlassian.jira.plugins.jira-development-integration-plugin:0","jira.rich.editor"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:calendar-en","jira.webresources:calendar-localisation-moment","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init","com.atlassian.jira.jira-header-plugin:newsletter-signup-tip","com.atlassian.plugin.jslibs:underscore-1.8.3","com.atlassian.jira.plugins.jira-editor-plugin:tinymce","com.atlassian.jira.plugins.jira-editor-plugin:schema-builder","com.atlassian.jira.plugins.jira-editor-plugin:schema","com.atlassian.jira.plugins.jira-editor-plugin:i18n","com.atlassian.jira.plugins.jira-editor-plugin:wrm","com.atlassian.jira.plugins.jira-editor-plugin:converter-util","com.atlassian.jira.plugins.jira-editor-plugin:context-detector","com.atlassian.jira.plugins.jira-editor-plugin:context-manager","com.atlassian.jira.plugins.jira-editor-plugin:selection","com.atlassian.jira.plugins.jira-editor-plugin:instance","com.atlassian.jira.plugins.jira-editor-plugin:api","com.atlassian.jira.plugins.jira-editor-plugin:renderer","com.atlassian.jira.plugins.jira-editor-plugin:mentions","com.atlassian.jira.plugins.jira-editor-plugin:mentions-plugin","com.atlassian.jira.plugins.jira-editor-plugin:polyfil-string-ends-with","com.atlassian.jira.plugins.jira-editor-plugin:resources","com.atlassian.jira.plugins.jira-editor-plugin:converter"]}, + "1165": [{"name":"jira.project.centric.navigation.sidebar.load.project","properties":{},"timeDelta":-4894},{"name":"jira.project.sidebar.sprint.select","properties":{"sprintId":"all","initialLoad":true},"timeDelta":-4783},{"name":"jira-software.scrum.work.view","properties":{"boardId":55,"issuesCount":103,"epicsCount":73},"timeDelta":-4684},{"name":"whisper.hermes.messages.load.success","properties":{"messageCount":1,"userLocale":"en_US","userLanguage":"en","invalidLanguageCount":0,"initTime":3728,"initState":"interactive"},"timeDelta":-4273},{"name":"browser.metrics.navigation","properties":{"apdex":"0.5","firstPaint":"1942","isInitial":"true","journeyId":"9fa2b66b-0b68-4611-8c52-ff43bca9d45d","key":"jira.agile.work","navigationType":"1","readyForUser":"3379","redirectCount":"0","resourceLoadedEnd":"1548","resourceLoadedStart":254.7550000017509,"threshold":"1000","unloadEventStart":"204","unloadEventEnd":"204","fetchStart":"6","domainLookupStart":"6","domainLookupEnd":"6","connectStart":"6","connectEnd":"6","requestStart":"19","responseStart":"188","responseEnd":"326","domLoading":"216","domInteractive":"2044","domContentLoadedEventStart":"2044","domContentLoadedEventEnd":"2193","domComplete":"4094","loadEventStart":"4095","loadEventEnd":"4100","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36","correlationId":"d21da59bbbebbb","effectiveType":"4g","downlink":4.1,"rtt":100,"serverDuration":"64","dbConnsTimeInMs":"23","applicationHash":"e00b0abe8f1b188f0bb304a4c3b424f1180ba767","resourceTiming":"{\"☠\":[\"2,72,es,ba,7d,72,,72,72,72\",\"2,73,kw,d4,94,73,,73,73,73\",\"2,73,el,eg,ax,ax,,7h,7h,7h\",\"2,73,em,ek,ay,ax,,7h,7h,7h\",\"3,74,to,f0,be,bd,,7i,7i,7i\",\"3,74,170,ia,en,74,,74,74,74\",\"3,74,ie,i7,en,74,,74,74,74\",\"3,74,ig,ic,es,74,,74,74,74\",\"3,75,is,in,ez,75,,75,75,75\",\"3,75,mb,lz,ii,75,,75,75,75\",\"3,75,m7,m2,ii,75,,75,75,75\",\"2,76,ez,ex,bd,b9,,7h,7h,7h\",\"3,76,mi,me,is,76,,76,76,76\",\"3,76,127,126,ut,76,,76,76,76\",\"-1,9m,pg,pa,kx,9m,,9m,9m,9m\",\"3,9w,15y,15v,12a,9w,,9w,9w,9w\",\"5,10d,15b,159,10i,10d,,10d,10d,10d\",\"5,19o,1dz,1dx,19r,19o,,19o,19o,19o\",\"4,1go,1mf,1md,1i5,1go,,1go,1go,1go\",\"5,1ny,1s0,1rz,1o2,1ny,,1ny,1ny,1ny\",\"2,1po,1tg,1tf,1pq,1po,,1po,1po,1po\",\"3,1pp,1tg,1td,1pr,1pp,,1pp,1pp,1pp\",\"5,1ts,1xx,1xw,1tx,1ts,,1ts,1ts,1ts\",\"3,1y3,21t,21p,1y5,1y3,,1y3,1y3,1y3\",\"3,1y4,222,21v,1y8,1y4,,1y4,1y4,1y4\",\"3,1y5,21x,21r,1y8,1y5,,1y5,1y5,1y5\",\"3,1y7,221,21z,1ya,1y7,,1y7,1y7,1y7\",\"3,1y8,2ci,21x,1ya,1y8,,1y8,1y8,1y8\",\"5,25b,2b2,2ax,25r,25b,,25b,25b,25b\",\"5,2eq,2it,2is,2f2,2eq,,2eq,2eq,2eq\"]}","mark.bigPipe.sidebar-id.start":"[1993]","mark.bigPipe.sidebar-id.end":"[1995]","userTimingRaw":"{\"marks\":{\"bigPipe.sidebar-id.start\":[1993],\"bigPipe.sidebar-id.end\":[1995]},\"measures\":{}}","experiments":"[]","dbReadsTimeInMs":"","serverHeadDuration":"undefined","connectionEffectiveType":"4g","connectionDownlink":4.1,"connectionRTT":100},"timeDelta":-3830}] + }, + "view_backlog": { + "1210": {"r":[],"c":["jira.webresources:mentions-feature"],"xc":["_super","gh-rapid-plan","jira.project.sidebar","jira.global","atl.general","com.atlassian.jira.projects.sidebar.init","greenhopper-rapid-non-gadget","gh-rapid-charts"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component"]}, + "1215": {"r":[],"c":["com.atlassian.jira.plugins.jira-development-integration-plugin:8","browser-metrics-plugin.contrib"],"xc":["_super","gh-rapid-plan","jira.project.sidebar","jira.global","atl.general","com.atlassian.jira.projects.sidebar.init","greenhopper-rapid-non-gadget","gh-rapid-charts","gh-rapid-exception","atl.global","jira.global.look-and-feel"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:calendar-localisation-moment"]}, + "1255": {"r":["com.atlassian.whisper.atlassian-whisper-plugin:atlassian-whisper-hermes"],"c":["jira.project.sidebar","jira.project.sidebar.software","gh-rapid-plan"],"xc":["_super","gh-rapid-plan","jira.project.sidebar","jira.global","atl.general","com.atlassian.jira.projects.sidebar.init","greenhopper-rapid-non-gadget","gh-rapid-charts","gh-rapid-exception","atl.global","jira.global.look-and-feel","com.atlassian.jira.plugins.jira-development-integration-plugin:8","browser-metrics-plugin.contrib"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:calendar-localisation-moment","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init"]}, + "1260": [{"name":"quicksearch.enabled","properties":{},"timeDelta":-804},{"name":"RapidBoard.show","timeDelta":-782},{"name":"RapidBoard.show.scrum","properties":{"boardId":55},"timeDelta":-716},{"name":"bigpipe.sidebar.render.success","properties":{},"timeDelta":-519},{"name":"atst.healthcheck.sensors.page-protocols","properties":{"resourceProtocols":"http/1.1","navigationProtocol":"http/1.1","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36"},"timeDelta":-503}], + "1265": [{"name":"jira.project.centric.navigation.sidebar.load.project","properties":{},"timeDelta":-5560},{"name":"jira-software.scrum.plan.view","properties":{"boardType":"scrum","backlogIssueCount":265,"boardId":55,"sprintsOnBoard":2,"activeSprints":2,"futureSprints":0,"totalIssueCount":310,"epicsCount":-1},"timeDelta":-5196},{"name":"browser.metrics.navigation","properties":{"apdex":"0","firstPaint":"2136","isInitial":"true","journeyId":"9fa2b66b-0b68-4611-8c52-ff43bca9d45d","key":"jira.agile.plan","navigationType":"0","readyForUser":"4169","redirectCount":"0","resourceLoadedEnd":"1769","resourceLoadedStart":437.9400000034366,"threshold":"1000","unloadEventStart":"360","unloadEventEnd":"361","fetchStart":"4","domainLookupStart":"50","domainLookupEnd":"50","connectStart":"50","connectEnd":"173","requestStart":"174","responseStart":"338","responseEnd":"472","domLoading":"389","domInteractive":"2331","domContentLoadedEventStart":"2331","domContentLoadedEventEnd":"2587","domComplete":"3057","loadEventStart":"3057","loadEventEnd":"3071","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36","correlationId":"f6c8b8956c584e","effectiveType":"4g","downlink":3.3,"rtt":100,"serverDuration":"58","dbConnsTimeInMs":"19","applicationHash":"e00b0abe8f1b188f0bb304a4c3b424f1180ba767","resourceTiming":"{\"☠\":[\"2,c5,kg,gy,d6,c5,,c5,c5,c5\",\"2,c6,on,h6,d9,c6,,c6,c6,c6\",\"2,c6,kb,k4,gn,gm,,d7,d7,d7\",\"2,c6,k9,k6,gn,gm,,d7,d7,d7\",\"3,c7,z7,kt,h9,gx,,d9,d9,d8\",\"3,c7,18u,o1,ke,c7,,c7,c7,c7\",\"3,c8,o6,nw,kf,c8,,c8,c8,c8\",\"3,c9,o3,nz,kg,c9,,c9,c9,c9\",\"3,cb,o4,o2,kh,cb,,cb,cb,cb\",\"3,cc,rv,rs,o7,cc,,cc,cc,cc\",\"3,cd,s8,s2,od,cd,,cd,cd,cd\",\"2,ce,ka,k7,go,go,,d8,d8,d8\",\"3,ce,s9,s7,og,ce,,ce,ce,ce\",\"3,cf,146,140,103,cf,,cf,cf,cf\",\"-1,fu,tt,tq,op,fu,,fu,fu,fu\",\"3,g3,1d5,1cx,19d,g3,,g3,g3,g3\",\"5,193,1d7,1d3,19c,193,,193,193,193\",\"4,1ko,1re,1rc,1nv,1ko,,1ko,1ko,1ko\",\"5,1mz,1r3,1r1,1nc,1mz,,1mz,1mz,1mz\",\"5,1ya,22h,22f,1yj,1ya,,1ya,1ya,1ya\",\"2,20s,24r,24n,212,20s,,20s,20s,20s\",\"3,212,250,24y,21b,212,,212,212,212\",\"3,217,258,253,21e,217,,217,217,217\",\"5,2c7,2gg,2gd,2ci,2c7,,2c7,2c7,2c7\",\"3,2h9,2l2,2ky,2hf,2h9,,2h9,2h9,2h9\",\"3,2hb,2lh,2l8,2hm,2hb,,2hb,2hb,2hb\",\"3,2hd,2le,2l4,2ho,2hd,,2hd,2hd,2hd\",\"3,2hf,2lt,2l6,2ho,2hf,,2hf,2hf,2hf\",\"5,2ic,2my,2mw,2je,2ic,,2ic,2ic,2ic\",\"5,2od,2s9,2s6,2oh,2od,,2od,2od,2od\"]}","mark.bigPipe.sidebar-id.start":"[2251]","mark.bigPipe.sidebar-id.end":"[2257]","userTimingRaw":"{\"marks\":{\"bigPipe.sidebar-id.start\":[2251],\"bigPipe.sidebar-id.end\":[2257]},\"measures\":{}}","experiments":"[]","dbReadsTimeInMs":"","serverHeadDuration":"undefined","connectionEffectiveType":"4g","connectionDownlink":3.3,"connectionRTT":100},"timeDelta":-4821},{"name":"whisper.hermes.messages.load.success","properties":{"messageCount":1,"userLocale":"en_US","userLanguage":"en","invalidLanguageCount":0,"initTime":4422,"initState":"complete"},"timeDelta":-4593}] }, "browse_boards": { - "1205": {"r":[],"c":["com.pyxis.greenhopper.jira:gh-rapid-inline-editable"],"xc":["_super","gh-rapid-exception","gh-manage-boards","jira.global","atl.general","greenhopper-rapid-non-gadget","jira.general"],"xr":["com.atlassian.auiplugin:aui-labels","jira.webresources:global-static-adgs","jira.webresources:global-static"]}, - "1210": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","gh-rapid-exception","gh-manage-boards","jira.global","atl.general","greenhopper-rapid-non-gadget","jira.general","com.pyxis.greenhopper.jira:gh-rapid-inline-editable","atl.global","jira.global.look-and-feel"],"xr":["com.atlassian.auiplugin:aui-labels","jira.webresources:global-static-adgs","jira.webresources:global-static","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:calendar-en","jira.webresources:calendar-localisation-moment"]}, - "1215": {"r":[],"c":["jira.webresources:mentions-feature"],"xc":["_super","gh-rapid-exception","gh-manage-boards","jira.global","atl.general","greenhopper-rapid-non-gadget","jira.general","com.pyxis.greenhopper.jira:gh-rapid-inline-editable","atl.global","jira.global.look-and-feel","browser-metrics-plugin.contrib"],"xr":["com.atlassian.auiplugin:aui-labels","jira.webresources:global-static-adgs","jira.webresources:global-static","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:calendar-en","jira.webresources:calendar-localisation-moment","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init"]}, - "1225": {"r":["com.atlassian.jira.jira-header-plugin:newsletter-signup-tip"],"c":[],"xc":["_super","gh-rapid-exception","gh-manage-boards","jira.global","atl.general","greenhopper-rapid-non-gadget","jira.general","com.pyxis.greenhopper.jira:gh-rapid-inline-editable","atl.global","jira.global.look-and-feel","browser-metrics-plugin.contrib"],"xr":["com.atlassian.auiplugin:aui-labels","jira.webresources:global-static-adgs","jira.webresources:global-static","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:calendar-en","jira.webresources:calendar-localisation-moment","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init"]} + "1305": {"r":[],"c":["browser-metrics-plugin.contrib"],"xc":["_super","gh-rapid-exception","gh-manage-boards","jira.global","atl.general","greenhopper-rapid-non-gadget"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component"]}, + "1315": {"r":[],"c":["jira.webresources:mentions-feature"],"xc":["_super","gh-rapid-exception","gh-manage-boards","jira.global","atl.general","greenhopper-rapid-non-gadget","browser-metrics-plugin.contrib","atl.global","jira.global.look-and-feel"],"xr":["com.atlassian.jira.jira-tzdetect-plugin:tzdetect-banner-component","com.atlassian.jira.jira-tzdetect-plugin:tzdetect-lib","jira.webresources:calendar-localisation-moment","jira.webresources:bigpipe-js","jira.webresources:bigpipe-init"]}, + "1320": [{"name":"quicksearch.enabled","properties":{},"timeDelta":-1025}] } - } \ No newline at end of file diff --git a/app/locustio/jsm/agents/agents_http_actions.py b/app/locustio/jsm/agents/agents_http_actions.py index 45662b5ca..ed646292d 100644 --- a/app/locustio/jsm/agents/agents_http_actions.py +++ b/app/locustio/jsm/agents/agents_http_actions.py @@ -15,6 +15,7 @@ def agent_login_and_view_dashboard(locust, jsm_agent_dataset): locust.cross_action_storage[session_id] = dict() locust.session_data_storage = locust.cross_action_storage[session_id] locust.session_data_storage['app'] = 'jsm' + locust.session_data_storage['app_type'] = 'agent' params = Login() diff --git a/app/locustio/jsm/customers/customers_http_actions.py b/app/locustio/jsm/customers/customers_http_actions.py index 50ed63c71..62dc65caf 100644 --- a/app/locustio/jsm/customers/customers_http_actions.py +++ b/app/locustio/jsm/customers/customers_http_actions.py @@ -18,6 +18,7 @@ def customer_login_and_view_portals(locust): locust.cross_action_storage[session_id] = dict() locust.session_data_storage = locust.cross_action_storage[session_id] locust.session_data_storage['app'] = 'jsm' + locust.session_data_storage['app_type'] = 'customer' params = Login() diff --git a/app/reports_generation/scale_profile.yml b/app/reports_generation/scale_profile.yml index 848b7b356..55e404f22 100644 --- a/app/reports_generation/scale_profile.yml +++ b/app/reports_generation/scale_profile.yml @@ -2,11 +2,11 @@ column_name: "90% Line" runs: # fullPath should contain a full path to the directory with run results. E.g. /home/$USER/dc-app-performance-toolkit/jira/results/2019-08-06_18-41-08 - - runName: "Node 1" + - runName: "1 Node" fullPath: "" - - runName: "Node 2" + - runName: "2 Nodes" fullPath: "" - - runName: "Node 4" + - runName: "4 Nodes" fullPath: "" # Chart generation configs diff --git a/app/selenium_ui/bitbucket/pages/selectors.py b/app/selenium_ui/bitbucket/pages/selectors.py index 6d293b947..a279875fe 100644 --- a/app/selenium_ui/bitbucket/pages/selectors.py +++ b/app/selenium_ui/bitbucket/pages/selectors.py @@ -193,7 +193,7 @@ class PullRequestLocator: merge_spinner = (By.CSS_SELECTOR, "aui-spinner[size='small']") diagram_selector = {'6': (By.CSS_SELECTOR, 'div.diagram-image'), '7': (By.CLASS_NAME, 'branches-diagram')} pull_request_modal_merge_button = {'6': (By.CSS_SELECTOR, 'button.confirm-button'), - '7': (By.CSS_SELECTOR, "button[type='submit']")} + '7': (By.CSS_SELECTOR, ".merge-dialog button[type='submit']")} del_branch_checkbox_selector = {'6': (By.CSS_SELECTOR, 'span.pull-request-cleanup-checkbox-wrapper'), '7': (By.NAME, 'deleteSourceRef')} delete_branch_per_merge_checkbox = (By.CSS_SELECTOR, "input[type='checkbox']") diff --git a/app/selenium_ui/jsm/pages/agent_pages.py b/app/selenium_ui/jsm/pages/agent_pages.py index 269990400..412f6f3d0 100644 --- a/app/selenium_ui/jsm/pages/agent_pages.py +++ b/app/selenium_ui/jsm/pages/agent_pages.py @@ -99,14 +99,18 @@ def add_request_comment(self, rte_status): if rte_status: self.wait_until_available_to_switch(ViewCustomerRequestLocators.comment_text_field_RTE) tinymce_field = self.get_element(ViewCustomerRequestLocators.comment_tinymce_field) + self.driver.execute_script("arguments[0].scrollIntoView(true);", tinymce_field) self.action_chains().send_keys_to_element(tinymce_field, comment_text).perform() self.return_to_parent_frame() else: comment_text_field = self.get_element(ViewCustomerRequestLocators.comment_text_field) + self.driver.execute_script("arguments[0].scrollIntoView(true);", comment_text_field) self.action_chains().move_to_element(comment_text_field).click()\ .send_keys_to_element(comment_text_field, comment_text).perform() - self.get_element(ViewCustomerRequestLocators.comment_internally_btn).click() + comment_button = self.get_element(ViewCustomerRequestLocators.comment_internally_btn) + self.driver.execute_script("arguments[0].scrollIntoView(true);", comment_button) + comment_button.click() self.wait_until_visible(ViewCustomerRequestLocators.comment_collapsed_textarea) diff --git a/app/util/analytics/analytics.py b/app/util/analytics/analytics.py index 613fb5606..7c6768eb3 100644 --- a/app/util/analytics/analytics.py +++ b/app/util/analytics/analytics.py @@ -7,18 +7,21 @@ from util.analytics.log_reader import BztFileReader, ResultsFileReader from util.conf import TOOLKIT_VERSION from util.analytics.analytics_utils import get_os, convert_to_sec, get_timestamp, get_date, is_all_tests_successful, \ - uniq_user_id, generate_report_summary, get_first_elem, generate_test_actions_by_type + uniq_user_id, generate_report_summary, get_first_elem, generate_test_actions_by_type, get_crowd_sync_test_results JIRA = 'jira' CONFLUENCE = 'confluence' BITBUCKET = 'bitbucket' JSM = 'jsm' +CROWD = 'crowd' MIN_DEFAULTS = {JIRA: {'test_duration': 2700, 'concurrency': 200}, CONFLUENCE: {'test_duration': 2700, 'concurrency': 200}, BITBUCKET: {'test_duration': 3000, 'concurrency': 20, 'git_operations_per_hour': 14400}, - JSM: {'test_duration': 2700, 'customer_concurrency': 150, 'agent_concurrency': 50} + JSM: {'test_duration': 2700, 'customer_concurrency': 150, 'agent_concurrency': 50}, + CROWD: {'test_duration': 2700, 'concurrency': 1000} } +CROWD_RPS = {'server': 50, 1: 50, 2: 100, 4: 200} # Crowd requests per second for 1,2,4 nodes. BASE_URL = 'https://s7hdm2mnj1.execute-api.us-east-2.amazonaws.com/default/analytics_collector' SUCCESS_TEST_RATE = 95.00 @@ -52,6 +55,10 @@ def __init__(self, application: BaseApplication): if self.app_type == JSM: self.concurrency_agents = self.conf.agents_concurrency self.concurrency_customers = self.conf.customers_concurrency + if self.app_type == CROWD: + self.crowd_sync_test = get_crowd_sync_test_results(bzt_log) + self.ramp_up = application.config.ramp_up + self.total_actions_per_hour = application.config.total_actions_per_hour def is_analytics_enabled(self): return str(self.conf.analytics_collector).lower() in ['yes', 'true', 'y'] @@ -71,8 +78,10 @@ def is_success(self): if not load_test_rates: return False, f"Jmeter/Locust test results was not found." - if not self.selenium_test_rates: - return False, f"Selenium test results was not found." + # There are no selenium tests for Crowd + if self.app_type != CROWD: + if not self.selenium_test_rates: + return False, f"Selenium test results was not found." success = (is_all_tests_successful(load_test_rates) and is_all_tests_successful(self.selenium_test_rates)) @@ -96,6 +105,13 @@ def is_compliant(self): compliant = (self.actual_duration >= MIN_DEFAULTS[self.app_type]['test_duration'] and self.concurrency_customers >= MIN_DEFAULTS[self.app_type]['customer_concurrency'] and self.concurrency_agents >= MIN_DEFAULTS[self.app_type]['agent_concurrency']) + elif self.app_type == CROWD: + rps_compliant = CROWD_RPS[self.nodes_count] + total_actions_compliant = rps_compliant * 3600 + ramp_up_compliant = MIN_DEFAULTS[CROWD]['concurrency'] / rps_compliant + ramp_up = convert_to_sec(self.ramp_up) + compliant = (ramp_up >= ramp_up_compliant and self.total_actions_per_hour >= total_actions_compliant and + self.actual_duration >= MIN_DEFAULTS[self.app_type]['test_duration']) else: compliant = (self.actual_duration >= MIN_DEFAULTS[self.app_type]['test_duration'] and self.concurrency >= MIN_DEFAULTS[self.app_type]['concurrency']) @@ -113,6 +129,16 @@ def is_compliant(self): if self.concurrency_agents < MIN_DEFAULTS[JSM]['agent_concurrency']: err_msg.append(f"The concurrency_agents = {self.concurrency_agents} is less than " f"required value {MIN_DEFAULTS[JSM]['agent_concurrency']}.") + + elif self.app_type == CROWD: + if ramp_up < ramp_up_compliant: + err_msg.append(f"The run ramp-up {ramp_up} is less than minimum ramp-up " + f"required for the {self.nodes_count} nodes {ramp_up_compliant}") + if self.total_actions_per_hour < total_actions_compliant: + err_msg.append(f"The run total_actions_per_hour {self.total_actions_per_hour} is less " + f"than minimum total_actions_per_hour " + f"required for the {self.nodes_count} nodes {total_actions_compliant}") + else: if self.concurrency < MIN_DEFAULTS[self.app_type]['concurrency']: err_msg.append(f"Test run concurrency {self.concurrency} < than minimum test " diff --git a/app/util/analytics/analytics_utils.py b/app/util/analytics/analytics_utils.py index 749d9f889..a4606cb68 100644 --- a/app/util/analytics/analytics_utils.py +++ b/app/util/analytics/analytics_utils.py @@ -2,6 +2,7 @@ import platform import hashlib import getpass +import re import socket from datetime import datetime, timezone @@ -79,6 +80,12 @@ def generate_report_summary(collector): summary_report.append(f'Success|{success}') summary_report.append(f'Has app-specific actions|{bool(collector.app_specific_rates)}') + if collector.app_type.lower() == 'crowd': + summary_report.append( + f'Crowd users directory synchronization time|{collector.crowd_sync_test["crowd_users_sync"]}') + summary_report.append( + f'Crowd groups membership synchronization time|{collector.crowd_sync_test["crowd_group_membership_sync"]}') + summary_report.append('\nAction|Success Rate|90th Percentile|Status') load_test_rates = collector.jmeter_test_rates or collector.locust_test_rates @@ -94,7 +101,7 @@ def generate_report_summary(collector): summary_report.append(f'{key}|{value}|{collector.test_actions_timing[key]}|{status}|{APP_SPECIFIC_TAG}') max_summary_report_str_len = len(max({**load_test_rates, **collector.selenium_test_rates}.keys(), key=len)) - offset_1st = max_summary_report_str_len + 5 + offset_1st = max(max_summary_report_str_len + 5, 50) pretty_report = map(lambda x: format_string_summary_report(x, offset_1st), summary_report) write_to_file(pretty_report, summary_report_file) @@ -166,3 +173,16 @@ def generate_test_actions_by_type(test_actions, application): else: app_specific_actions.setdefault(test_action, value) return selenium_actions, jmeter_actions, locust_actions, app_specific_actions + + +def get_crowd_sync_test_results(bzt_log): + users_sync_template = 'Users synchronization: (.*) seconds' + membership_sync_template = 'Users membership synchronization: (.*) seconds' + users_sync_time = '' + membership_sync_time = '' + for line in bzt_log.bzt_log: + if re.search(users_sync_template, line): + users_sync_time = re.search(users_sync_template, line).group(1) + if re.search(membership_sync_template, line): + membership_sync_time = re.search(membership_sync_template, line).group(1) + return {"crowd_users_sync": users_sync_time, "crowd_group_membership_sync": membership_sync_time} diff --git a/app/util/analytics/application_info.py b/app/util/analytics/application_info.py index 0311e26c7..3fd105c4e 100644 --- a/app/util/analytics/application_info.py +++ b/app/util/analytics/application_info.py @@ -1,7 +1,8 @@ -from util.conf import JIRA_SETTINGS, CONFLUENCE_SETTINGS, BITBUCKET_SETTINGS, JSM_SETTINGS +from util.conf import JIRA_SETTINGS, CONFLUENCE_SETTINGS, BITBUCKET_SETTINGS, JSM_SETTINGS, CROWD_SETTINGS from util.api.jira_clients import JiraRestClient from util.api.confluence_clients import ConfluenceRestClient from util.api.bitbucket_clients import BitbucketRestClient +from util.api.crowd_clients import CrowdRestClient from lxml import etree import json @@ -9,6 +10,7 @@ CONFLUENCE = 'confluence' BITBUCKET = 'bitbucket' JSM = 'jsm' +CROWD = 'crowd' DEFAULT_ACTIONS = 'util/default_test_actions.json' @@ -128,6 +130,31 @@ def dataset_information(self): return f"{self.__issues_count()} issues" +class Crowd(BaseApplication): + type = CROWD + + @property + def version(self): + crowd_server_info = self.client.get_server_info() + return crowd_server_info.get('version', '') + + @property + def nodes_count(self): + cluster_nodes_info = self.client.get_cluster_nodes() + nodes_count = len(cluster_nodes_info) + return nodes_count if nodes_count > 0 else "server" + + def __users_count(self): + self.application_crowd_client = CrowdRestClient(host=CROWD_SETTINGS.server_url, + user=CROWD_SETTINGS.application_name, + password=CROWD_SETTINGS.application_password) + return len(self.application_crowd_client.search(start_index=0, max_results=-1, expand='user')) + + @property + def dataset_information(self): + return f"{self.__users_count()} users" + + class ApplicationSelector: APP_TYPE_MSG = ('ERROR: Please run util/analytics.py with application type as argument. ' 'E.g. python util/analytics.py jira/confluence/bitbucket/jsm') @@ -136,7 +163,7 @@ def __init__(self, app_name): self.application_type = self.__get_application_type(app_name) def __get_application_type(self, app_name): - if app_name.lower() not in [JIRA, CONFLUENCE, BITBUCKET, JSM]: + if app_name.lower() not in [JIRA, CONFLUENCE, BITBUCKET, JSM, CROWD]: raise SystemExit(self.APP_TYPE_MSG) return app_name.lower() @@ -150,3 +177,5 @@ def application(self): return Bitbucket(api_client=BitbucketRestClient, config_yml=BITBUCKET_SETTINGS) if self.application_type == JSM: return Jsm(api_client=JiraRestClient, config_yml=JSM_SETTINGS) + if self.application_type == CROWD: + return Crowd(api_client=CrowdRestClient, config_yml=CROWD_SETTINGS) diff --git a/app/util/api/crowd_clients.py b/app/util/api/crowd_clients.py new file mode 100644 index 000000000..b9f24b5c8 --- /dev/null +++ b/app/util/api/crowd_clients.py @@ -0,0 +1,99 @@ +from util.api.abstract_clients import RestClient, LOGIN_POST_HEADERS + + +BATCH_SIZE_USERS = 1000 + + +class CrowdRestClient(RestClient): + + def add_user(self, + name: str, + password: str, + first_name: str, + last_name: str, + display_name: str = None, + email: str = None, + active: bool = True): + api_url = self.host + "/rest/usermanagement/1/user" + payload = { + "name": name, + "password": {"value": password}, + "active": active, + "first-name": first_name, + "last-name": last_name, + "display-name": display_name or f"{first_name} {last_name}", + "email": email or name + '@localdomain.com' + } + + response = self.post(api_url, "Could not create crowd user", body=payload) + + return response.json() + + def search(self, entity_type: str = "user", start_index: int = 0, max_results: int = 1000, restriction: str = '', + expand: str = 'user'): + api_url = self.host + f"/rest/usermanagement/1/search" \ + f"?entity-type={entity_type}" \ + f"&start-index={start_index}&max-results={max_results}&restriction={restriction}" \ + f"&expand={expand}" + response = self.get(api_url, "Search failed") + + return [i['name'] for i in response.json()[f'{entity_type}s']] + + def users_search_parallel(self, cql: str = '', max_results: int = 1000): + """ + Parallel version + """ + from multiprocessing import cpu_count + from multiprocessing.pool import ThreadPool + print("Users parallel search") + + if max_results % BATCH_SIZE_USERS == 0: + loop_count = max_results // BATCH_SIZE_USERS + last_BATCH_SIZE_USERS = BATCH_SIZE_USERS + else: + loop_count = max_results // BATCH_SIZE_USERS + 1 + last_BATCH_SIZE_USERS = max_results % BATCH_SIZE_USERS + + def search_users(i): + nonlocal loop_count, last_BATCH_SIZE_USERS + if i == loop_count - 1: + loop_max_results = last_BATCH_SIZE_USERS + else: + loop_max_results = BATCH_SIZE_USERS + + start_index = BATCH_SIZE_USERS * i + + loop_users = self.search( + entity_type='user', start_index=start_index, max_results=loop_max_results, restriction=cql) + + print(".", end="", flush=True) + return loop_users + + num_cores = cpu_count() + pool = ThreadPool(processes=num_cores*2) + loop_users_list = pool.map(search_users, [i for i in range(loop_count)]) + print("") # new line + users = [user for loop_users in loop_users_list for user in loop_users] + return users + + def group_members(self, group_name: str, start_index: int = 0, max_results: int = 1000): + api_url = self.host + f"/rest/usermanagement/1/group/user/direct" \ + f"?groupname={group_name}&start-index={start_index}&max-results={max_results}" + r = self.get(api_url, "Group members call failed") + return r.json() + + def get_group_membership(self): + api_url = self.host + '/rest/usermanagement/1/group/membership' + self.headers = {'Accept': 'application/xml', 'Content-Type': 'application/xml'} + response = self.get(api_url, 'Can not get group memberships') + return response.content + + def get_server_info(self): + api_url = self.host + '/rest/admin/1.0/server-info' + response = self.get(api_url, 'Can not get Crowd server info') + return response.json() + + def get_cluster_nodes(self): + api_url = self.host + '/rest/atlassian-cluster-monitoring/cluster/nodes' + response = self.get(api_url, 'Can not get Crowd cluster nodes information') + return response.json() diff --git a/app/util/api/jira_clients.py b/app/util/api/jira_clients.py index 004fc0351..1916574e9 100644 --- a/app/util/api/jira_clients.py +++ b/app/util/api/jira_clients.py @@ -1,6 +1,7 @@ from selenium.common.exceptions import WebDriverException from util.api.abstract_clients import RestClient, LOGIN_POST_HEADERS, JSM_EXPERIMENTAL_HEADERS +from selenium_ui.conftest import retry BATCH_SIZE_BOARDS = 1000 BATCH_SIZE_USERS = 1000 @@ -46,6 +47,7 @@ def get_boards(self, start_at=0, max_results=100, board_type=None, name=None, pr return boards_list + @retry() def get_users(self, username='.', start_at=0, max_results=1000, include_active=True, include_inactive=False): """ Returns a list of users that match the search string. This resource cannot be accessed anonymously. @@ -118,6 +120,7 @@ def issues_search(self, jql='order by key', start_at=0, max_results=1000, fields return issues + @retry() def get_total_issues_count(self, jql: str = ''): api_url = f'{self.host}/rest/api/2/search' body = {"jql": jql if jql else "order by key", diff --git a/app/util/api/jsm_clients.py b/app/util/api/jsm_clients.py index d3444a4d9..0cf8dac85 100644 --- a/app/util/api/jsm_clients.py +++ b/app/util/api/jsm_clients.py @@ -1,5 +1,6 @@ from util.api.abstract_clients import JSM_EXPERIMENTAL_HEADERS from util.api.abstract_clients import RestClient +from selenium_ui.conftest import retry BATCH_SIZE_USERS = 1000 @@ -119,6 +120,7 @@ def get_requests(self, start_at: int = 0, max_results: int = 100, auth: tuple = max_results = last_loop_remainder return requests + @retry() def get_queue(self, service_desk_id: int, start: int = 0): """ Returns the customer request for a given request Id/key. @@ -130,6 +132,7 @@ def get_queue(self, service_desk_id: int, start: int = 0): response = self.get(api_url, f"Could not get queues for service desk {service_desk_id}") return response.json()['values'] + @retry() def get_request_types(self, service_desk_id): """ Returns all request types from a service desk, for a given service desk Id. @@ -153,6 +156,7 @@ def get_request_type_fields(self, service_desk_id, request_type_id): f"service desk id {service_desk_id} and request type is {request_type_id}") return response.json()['requestTypeFields'] + @retry() def get_all_service_desks(self): """ Returns all service desks in the Jira Service Desk application. @@ -172,6 +176,7 @@ def get_all_service_desks(self): start = start + limit return results + @retry() def get_servicedesk_info(self): """ This resource represents the Jira Service Desk application. @@ -181,6 +186,7 @@ def get_servicedesk_info(self): response = self.get(api_url, "Could not get request Service desk info.") return response + @retry() def get_service_desk_reports(self, project_key: str = ''): api_url = self.host + f"/rest/servicedesk/1/{project_key}/webfragments/sections/sd-reports-nav-custom-section" payload = { diff --git a/app/util/bitbucket/populate_db.sh b/app/util/bitbucket/populate_db.sh index 966017832..442cb4a41 100644 --- a/app/util/bitbucket/populate_db.sh +++ b/app/util/bitbucket/populate_db.sh @@ -23,7 +23,7 @@ BITBUCKET_DB_PASS="Password1!" BITBUCKET_AUTO_DECLINE_VERSION="7.7.0" # BITBUCKET version variables -SUPPORTED_BITBUCKET_VERSIONS=(6.10.9 7.0.5 7.6.4) +SUPPORTED_BITBUCKET_VERSIONS=(6.10.11 7.0.5 7.6.7) BITBUCKET_VERSION=$(sudo su bitbucket -c "cat ${BITBUCKET_VERSION_FILE}") if [[ -z "$BITBUCKET_VERSION" ]]; then echo The $BITBUCKET_VERSION_FILE file does not exists or emtpy. Please check if BITBUCKET_VERSION_FILE variable \ diff --git a/app/util/bitbucket/upload_attachments.sh b/app/util/bitbucket/upload_attachments.sh index c0eb53cf3..e69bebd4b 100644 --- a/app/util/bitbucket/upload_attachments.sh +++ b/app/util/bitbucket/upload_attachments.sh @@ -6,7 +6,7 @@ pgrep nfsd > /dev/null && echo "NFS found" || { echo NFS process was not found. ################### Variables section ################### # Bitbucket version variables BITBUCKET_VERSION_FILE="/media/atl/bitbucket/shared/bitbucket.version" -SUPPORTED_BITBUCKET_VERSIONS=(6.10.9 7.0.5 7.6.4) +SUPPORTED_BITBUCKET_VERSIONS=(6.10.11 7.0.5 7.6.7) BITBUCKET_VERSION=$(sudo su bitbucket -c "cat ${BITBUCKET_VERSION_FILE}") if [[ -z "$BITBUCKET_VERSION" ]]; then echo The $BITBUCKET_VERSION_FILE file does not exists or emtpy. Please check if BITBUCKET_VERSION_FILE variable \ diff --git a/app/util/conf.py b/app/util/conf.py index 430b6ca21..3382ebc84 100644 --- a/app/util/conf.py +++ b/app/util/conf.py @@ -1,8 +1,8 @@ import yaml -from util.project_paths import JIRA_YML, CONFLUENCE_YML, BITBUCKET_YML, JSM_YML +from util.project_paths import JIRA_YML, CONFLUENCE_YML, BITBUCKET_YML, JSM_YML, CROWD_YML -TOOLKIT_VERSION = '4.2.0' +TOOLKIT_VERSION = '5.0.0' def read_yml_file(file): @@ -25,7 +25,6 @@ def __init__(self, config_yml): self.duration = self.get_property('test_duration') self.analytics_collector = self.get_property('allow_analytics') self.load_executor = self.get_property('load_executor') - self.webdriver_visible = self.get_property('WEBDRIVER_VISIBLE') self.secure = self.get_property('secure') @property @@ -42,6 +41,7 @@ class JiraSettings(BaseAppSettings): def __init__(self, config_yml): super().__init__(config_yml) + self.webdriver_visible = self.get_property('WEBDRIVER_VISIBLE') self.concurrency = self.get_property('concurrency') self.custom_dataset_query = self.get_property('custom_dataset_query') or "" self.verbose = self.settings['verbose'] @@ -52,6 +52,7 @@ class ConfluenceSettings(BaseAppSettings): def __init__(self, config_yml): super().__init__(config_yml) + self.webdriver_visible = self.get_property('WEBDRIVER_VISIBLE') self.concurrency = self.get_property('concurrency') self.custom_dataset_query = self.get_property('custom_dataset_query') or "" self.verbose = self.settings['verbose'] @@ -62,6 +63,7 @@ class BitbucketSettings(BaseAppSettings): def __init__(self, config_yml): super().__init__(config_yml) + self.webdriver_visible = self.get_property('WEBDRIVER_VISIBLE') self.concurrency = self.get_property('concurrency') self.verbose = self.settings['verbose'] self.total_actions_per_hour = self.get_property('total_actions_per_hour') @@ -71,6 +73,7 @@ class JsmSettings(BaseAppSettings): def __init__(self, config_yml): super().__init__(config_yml) + self.webdriver_visible = self.get_property('WEBDRIVER_VISIBLE') self.agents_concurrency = self.get_property('concurrency_agents') self.agents_total_actions_per_hr = self.get_property('total_actions_per_hour_agents') self.customers_total_actions_per_hr = self.get_property('total_actions_per_hour_customers') @@ -80,7 +83,19 @@ def __init__(self, config_yml): self.verbose = self.settings['verbose'] +class CrowdSettings(BaseAppSettings): + + def __init__(self, config_yml): + super().__init__(config_yml) + self.concurrency = self.get_property('concurrency') + self.application_name = self.get_property('application_name') + self.application_password = self.get_property('application_password') + self.total_actions_per_hour = self.get_property('total_actions_per_hour') + self.ramp_up = self.get_property('ramp-up') + + JIRA_SETTINGS = JiraSettings(config_yml=JIRA_YML) CONFLUENCE_SETTINGS = ConfluenceSettings(config_yml=CONFLUENCE_YML) BITBUCKET_SETTINGS = BitbucketSettings(config_yml=BITBUCKET_YML) JSM_SETTINGS = JsmSettings(config_yml=JSM_YML) +CROWD_SETTINGS = CrowdSettings(config_yml=CROWD_YML) diff --git a/app/util/confluence/populate_db.sh b/app/util/confluence/populate_db.sh index c5014ee0d..ec189ff6f 100644 --- a/app/util/confluence/populate_db.sh +++ b/app/util/confluence/populate_db.sh @@ -20,7 +20,7 @@ CONFLUENCE_DB_PASS="Password1!" SELECT_CONFLUENCE_SETTING_SQL="select BANDANAVALUE from BANDANA where BANDANACONTEXT = '_GLOBAL' and BANDANAKEY = 'atlassian.confluence.settings';" # Confluence version variables -SUPPORTED_CONFLUENCE_VERSIONS=(7.0.5 7.4.8) +SUPPORTED_CONFLUENCE_VERSIONS=(7.0.5 7.4.9) if [[ ! $(systemctl status confluence) ]]; then echo "The Confluence service was not found on this host." \ diff --git a/app/util/confluence/upload_attachments.sh b/app/util/confluence/upload_attachments.sh index d4252ff6b..50a62d58f 100644 --- a/app/util/confluence/upload_attachments.sh +++ b/app/util/confluence/upload_attachments.sh @@ -4,7 +4,7 @@ ################### Variables section ################### # Confluence version variables CONFLUENCE_VERSION_FILE="/media/atl/confluence/shared-home/confluence.version" -SUPPORTED_CONFLUENCE_VERSIONS=(7.0.5 7.4.8) +SUPPORTED_CONFLUENCE_VERSIONS=(7.0.5 7.4.9) CONFLUENCE_VERSION=$(sudo su confluence -c "cat ${CONFLUENCE_VERSION_FILE}") if [[ -z "$CONFLUENCE_VERSION" ]]; then echo The $CONFLUENCE_VERSION_FILE file does not exists or emtpy. Please check if CONFLUENCE_VERSION_FILE variable \ diff --git a/app/util/crowd/populate_db.sh b/app/util/crowd/populate_db.sh new file mode 100644 index 000000000..bc5be2cac --- /dev/null +++ b/app/util/crowd/populate_db.sh @@ -0,0 +1,162 @@ +#!/bin/bash + +################### Variables section ################### +# Command to install psql client for Amazon Linux 2. +# In case of different distributive, please adjust accordingly or install manually. +INSTALL_PSQL_CMD="amazon-linux-extras install -y postgresql11" + +# DB config file location (dbconfig.xml) +DB_CONFIG="/usr/lib/systemd/system/crowd.service" + +# Depending on Crowd installation directory +CROWD_VERSION_FILE="/media/atl/crowd/shared/crowd.version" + +# DB admin user name, password and DB name +CROWD_DB_NAME="crowd" +CROWD_DB_USER="postgres" +CROWD_DB_PASS="Password1!" + +# Crowd version variables +SUPPORTED_CROWD_VERSIONS=(4.3.0) + +if [[ ! $(systemctl status crowd) ]]; then + echo "The Crowd service was not found on this host." \ + "Please make sure you are running this script on a host that is running Crowd." + exit 1 +fi + +CROWD_VERSION=$(sudo su crowd -c "cat ${CROWD_VERSION_FILE}") +if [[ -z "$CROWD_VERSION" ]]; then + echo The $CROWD_VERSION_FILE file does not exists or emtpy. Please check if CROWD_VERSION_FILE variable \ + has a valid file path of the Crowd version file or set your Cluster CROWD_VERSION explicitly. + exit 1 +fi +echo "Crowd Version: ${CROWD_VERSION}" + +# Datasets AWS bucket and db dump name +DATASETS_AWS_BUCKET="https://centaurus-datasets.s3.amazonaws.com/crowd" +DATASETS_SIZE="large" +DB_DUMP_NAME="db.dump" + +################### End of variables section ################### + +# Check if Crowd version is supported +if [[ ! "${SUPPORTED_CROWD_VERSIONS[*]}" =~ ${CROWD_VERSION} ]]; then + echo "Crowd Version: ${CROWD_VERSION} is not officially supported by Data Center App Performance Toolkit." + echo "Supported Crowd Versions: ${SUPPORTED_CROWD_VERSIONS[*]}" + echo "!!! Warning !!! Dump from version ${SUPPORTED_CROWD_VERSIONS[0]} would be used" +fi + +DB_DUMP_URL="${DATASETS_AWS_BUCKET}/${SUPPORTED_CROWD_VERSIONS[0]}/${DATASETS_SIZE}/${DB_DUMP_NAME}" + +echo "!!! Warning !!!" +echo # move to a new line +echo "This script restores Postgres DB from SQL DB dump for Сrowd DC created with AWS Quickstart defaults." +echo "You can review or modify default variables in 'Variables section' of this script." +echo # move to a new line +echo "Variables:" +echo "DB_CONFIG=${DB_CONFIG}" +echo "CROWD_DB_NAME=${CROWD_DB_NAME}" +echo "CROWD_DB_USER=${CROWD_DB_USER}" +echo "CROWD_DB_PASS=${CROWD_DB_PASS}" +echo "DB_DUMP_URL=${DB_DUMP_URL}" +echo # move to a new line +read -p "I confirm that variables are correct and want to proceed (y/n)? " -n 1 -r +echo # move to a new line +if [[ ! $REPLY =~ ^[Yy]$ ]]; then + echo "Script was canceled." + exit 1 +fi + +echo "Step1: Check Postgres Client" +if ! [[ -x "$(command -v psql)" ]]; then + echo "Install Postgres client" + sudo su -c "${INSTALL_PSQL_CMD}" + if [[ $? -ne 0 ]]; then + echo "Postgres Client was NOT installed." + echo "Check correctness of install command or install Postgres client manually." + echo "INSTALL_PSQL_CMD=${INSTALL_PSQL_CMD}" + exit 1 + fi +else + echo "Postgres client is already installed" +fi +echo "Current PostgreSQL version is $(psql -V)" + +echo "Step2: Get DB Host and check DB connection" +DB_HOST=$(sudo su -c "cat ${DB_CONFIG} | grep 'jdbc:postgresql' | cut -d'/' -f3 | cut -d':' -f1") +if [[ -z ${DB_HOST} ]]; then + echo "DataBase URL was not found in ${DB_CONFIG}" + exit 1 +fi +echo "DB_HOST=${DB_HOST}" + +echo "Check DB connection" +PGPASSWORD=${CROWD_DB_PASS} pg_isready -U ${CROWD_DB_USER} -h ${DB_HOST} +if [[ $? -ne 0 ]]; then + echo "Connection to DB failed. Please check correctness of following variables:" + echo "CROWD_DB_NAME=${CROWD_DB_NAME}" + echo "CROWD_DB_USER=${CROWD_DB_USER}" + echo "CROWD_DB_PASS=${CROWD_DB_PASS}" + echo "DB_HOST=${DB_HOST}" + exit 1 +fi + +echo "Step3: Stop Crowd" +sudo systemctl stop crowd +if [[ $? -ne 0 ]]; then + echo "Crowd did not stop. Please try to rerun script." + exit 1 +fi + +echo "Step4: Download DB dump" +rm -rf ${DB_DUMP_NAME} +ARTIFACT_SIZE_BYTES=$(curl -sI ${DB_DUMP_URL} | grep "Content-Length" | awk {'print $2'} | tr -d '[:space:]') +ARTIFACT_SIZE_GB=$((${ARTIFACT_SIZE_BYTES}/1024/1024/1024)) +FREE_SPACE_KB=$(df -k --output=avail "$PWD" | tail -n1) +FREE_SPACE_GB=$((${FREE_SPACE_KB}/1024/1024)) +REQUIRED_SPACE_GB=$((5 + ${ARTIFACT_SIZE_GB})) +if [[ ${FREE_SPACE_GB} -lt ${REQUIRED_SPACE_GB} ]]; then + echo "Not enough free space for download." + echo "Free space: ${FREE_SPACE_GB} GB" + echo "Required space: ${REQUIRED_SPACE_GB} GB" + exit 1 +fi +# use computer style progress bar +time wget --progress=dot:giga ${DB_DUMP_URL} +if [[ $? -ne 0 ]]; then + echo "DB dump download failed! Pls check available disk space." + exit 1 +fi + +echo "Step5: SQL Restore" +echo "Drop DB" +PGPASSWORD=${CROWD_DB_PASS} dropdb -U ${CROWD_DB_USER} -h ${DB_HOST} ${CROWD_DB_NAME} +if [[ $? -ne 0 ]]; then + echo "Drop DB failed." + exit 1 +fi +sleep 5 +echo "Create DB" +PGPASSWORD=${CROWD_DB_PASS} createdb -U ${CROWD_DB_USER} -h ${DB_HOST} -T template0 ${CROWD_DB_NAME} +if [[ $? -ne 0 ]]; then + echo "Create DB failed." + exit 1 +fi +sleep 5 +echo "PG Restore" +time PGPASSWORD=${CROWD_DB_PASS} pg_restore --schema=public -v -j 8 -U ${CROWD_DB_USER} -h ${DB_HOST} -d ${CROWD_DB_NAME} ${DB_DUMP_NAME} +if [[ $? -ne 0 ]]; then + echo "SQL Restore failed!" + exit 1 +fi + +echo "Step6: Start Crowd" +sudo systemctl start crowd +rm -rf ${DB_DUMP_NAME} + +echo "DCAPT util script execution is finished successfully." +echo # move to a new line + +echo "Important: new admin user credentials are admin/admin" +echo "Wait a couple of minutes until Crowd is started." diff --git a/app/util/data_preparation/confluence_prepare_data.py b/app/util/data_preparation/confluence_prepare_data.py index b63440f2a..1982c4c0c 100644 --- a/app/util/data_preparation/confluence_prepare_data.py +++ b/app/util/data_preparation/confluence_prepare_data.py @@ -92,8 +92,7 @@ def __get_custom_pages(confluence_api, count, cql): def __get_blogs(confluence_api, count): blogs = confluence_api.get_content_search( 0, count, cql='type=blogpost' - ' and title !~ Performance' - ' and text !~ BLOG_10') # filter out too heavy blog post page type + ' and title !~ Performance') if not blogs: raise SystemExit(f"There are no Blog posts in Confluence accessible by a random performance user: " f"{confluence_api.user}") diff --git a/app/util/data_preparation/crowd_prepare_data.py b/app/util/data_preparation/crowd_prepare_data.py new file mode 100644 index 000000000..791b55bb0 --- /dev/null +++ b/app/util/data_preparation/crowd_prepare_data.py @@ -0,0 +1,73 @@ +import urllib3 +import random +import string + +from util.conf import CROWD_SETTINGS +from util.api.crowd_clients import CrowdRestClient +from util.project_paths import CROWD_USERS + + +urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) + + +USERS = "users" +DEFAULT_USER_PASSWORD = 'password' +DEFAULT_USER_PREFIX = 'performance_' +USER_SEARCH_CQL = f'name={DEFAULT_USER_PREFIX}*' +ERROR_LIMIT = 10 + +USERS_COUNT = 100000 + + +def generate_random_string(length=20): + return "".join([random.choice(string.ascii_lowercase) for _ in range(length)]) + + +def __get_users(crowd_api, count): + cur_perf_users = crowd_api.users_search_parallel(cql=USER_SEARCH_CQL, max_results=count) + if len(cur_perf_users) >= count: + print(f'{USERS_COUNT} performance test users were found') + return cur_perf_users + else: + raise SystemExit(f'Your Atlassian Crowd instance does not have enough users. ' + f'Current users count {len(cur_perf_users)} out of {count}.') + + +def __create_data_set(crowd_api): + dataset = dict() + dataset[USERS] = __get_users(crowd_api, USERS_COUNT) + + print(f'Users count: {len(dataset[USERS])}') + + return dataset + + +def write_test_data_to_files(dataset): + + users = [f"{user},{DEFAULT_USER_PASSWORD}" for user in dataset[USERS]] + __write_to_file(CROWD_USERS, users) + + +def __write_to_file(file_path, items): + with open(file_path, 'w') as f: + for item in items: + f.write(f"{item}\n") + + +def main(): + print("Started preparing data") + + url = CROWD_SETTINGS.server_url + print("Server url: ", url) + + client = CrowdRestClient(url, CROWD_SETTINGS.application_name, + CROWD_SETTINGS.application_password, verify=CROWD_SETTINGS.secure) + + dataset = __create_data_set(client) + write_test_data_to_files(dataset) + + print("Finished preparing data") + + +if __name__ == "__main__": + main() diff --git a/app/util/data_preparation/crowd_sync_check.py b/app/util/data_preparation/crowd_sync_check.py new file mode 100644 index 000000000..bcda811a4 --- /dev/null +++ b/app/util/data_preparation/crowd_sync_check.py @@ -0,0 +1,44 @@ +import urllib3 +from timeit import default_timer as timer +import functools +from datetime import timedelta + +from util.conf import CROWD_SETTINGS +from util.api.crowd_clients import CrowdRestClient + + +urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) + + +def print_timing(message): + assert message is not None, "Message is not passed to print_timing decorator" + + def deco_wrapper(func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + start = timer() + result = func(*args, **kwargs) + end = timer() + print(f"{message}: {timedelta(seconds=end-start)} seconds") + return result + return wrapper + return deco_wrapper + + +@print_timing('Users synchronization') +def get_users(client): + users = client.search(start_index=0, max_results='-1', expand='user') + return users + + +@print_timing('Users membership synchronization') +def get_users_membership(client): + membership = client.get_group_membership() + return membership + + +if __name__ == "__main__": + client = CrowdRestClient(CROWD_SETTINGS.server_url, CROWD_SETTINGS.application_name, + CROWD_SETTINGS.application_password, verify=CROWD_SETTINGS.secure) + get_users(client) + get_users_membership(client) diff --git a/app/util/default_test_actions.json b/app/util/default_test_actions.json index a83b1f998..22e824736 100644 --- a/app/util/default_test_actions.json +++ b/app/util/default_test_actions.json @@ -101,22 +101,21 @@ ], "locust": [ "locust_login_and_view_dashboard", - "locust_comment_page", + "locust_view_page", "locust_view_dashboard", - "locust_view_page:open_page", - "locust_create_and_edit_page:create_page_editor", - "locust_upload_attachment", "locust_view_blog", "locust_search_cql:recently_viewed", - "locust_create_blog:blog_editor", - "locust_view_page:view_page_tree", - "locust_create_and_edit_page:create_page", - "locust_like_page", - "locust_view_attachment", "locust_search_cql:search_results", - "locust_create_blog:feel_and_publish", + "locust_comment_page", + "locust_create_and_edit_page:create_page_editor", + "locust_create_and_edit_page:create_page", "locust_create_and_edit_page:open_editor", - "locust_create_and_edit_page:edit_page" + "locust_create_and_edit_page:edit_page", + "locust_upload_attachment", + "locust_create_blog:blog_editor", + "locust_create_blog:feel_and_publish", + "locust_like_page", + "locust_view_attachment" ] }, "bitbucket": { @@ -256,5 +255,6 @@ "locust_customer_share_request_with_org:add_org", "locust_customer_share_request_with_org:remove_org" ] - } + }, + "crowd": {"jmeter": ["jmeter_user_auth"], "selenium": [], "locust": []} } \ No newline at end of file diff --git a/app/util/jira/populate_db.sh b/app/util/jira/populate_db.sh index 645308402..c659b1ac2 100644 --- a/app/util/jira/populate_db.sh +++ b/app/util/jira/populate_db.sh @@ -44,8 +44,9 @@ JIRA_DB_USER="postgres" JIRA_DB_PASS="Password1!" # Jira/JSM supported versions -SUPPORTED_JIRA_VERSIONS=(8.5.12 8.13.4) -SUPPORTED_JSM_VERSIONS=(4.5.12 4.13.4) + +SUPPORTED_JIRA_VERSIONS=(8.5.15 8.13.7) +SUPPORTED_JSM_VERSIONS=(4.5.15 4.13.7) SUPPORTED_VERSIONS=("${SUPPORTED_JIRA_VERSIONS[@]}") # JSM section diff --git a/app/util/jira/upload_attachments.sh b/app/util/jira/upload_attachments.sh index 3b01325c8..5b60e1607 100644 --- a/app/util/jira/upload_attachments.sh +++ b/app/util/jira/upload_attachments.sh @@ -27,8 +27,9 @@ fi JIRA_VERSION_FILE="/media/atl/jira/shared/jira-software.version" # Jira/JSM supported versions -SUPPORTED_JIRA_VERSIONS=(8.5.12 8.13.4) -SUPPORTED_JSM_VERSIONS=(4.5.12 4.13.4) + +SUPPORTED_JIRA_VERSIONS=(8.5.15 8.13.7) +SUPPORTED_JSM_VERSIONS=(4.5.15 4.13.7) SUPPORTED_VERSIONS=("${SUPPORTED_JIRA_VERSIONS[@]}") if [[ ${jsm} == 1 ]]; then diff --git a/app/util/jmeter/start_jmeter_ui.py b/app/util/jmeter/start_jmeter_ui.py index dbc085fb3..a6713d3c4 100644 --- a/app/util/jmeter/start_jmeter_ui.py +++ b/app/util/jmeter/start_jmeter_ui.py @@ -19,13 +19,16 @@ CONFLUENCE = "confluence" BITBUCKET = "bitbucket" JSM = "jsm" +CROWD = "crowd" APP_DIR = Path(__file__).resolve().parents[2] PROPERTIES = APP_DIR / "util" / "jmeter" / "jmeter.properties" JIRA_YML = APP_DIR / "jira.yml" +CROWD_YML = APP_DIR / "crowd.yml" CONFLUENCE_YML = APP_DIR / "confluence.yml" BITBUCKET_YML = APP_DIR / "bitbucket.yml" JSM_YML = APP_DIR / "jsm.yml" JIRA_JMX = APP_DIR / "jmeter" / "jira.jmx" +CROWD_JMX = APP_DIR / "jmeter" / "crowd.jmx" CONFLUENCE_JMX = APP_DIR / "jmeter" / "confluence.jmx" BITBUCKET_JMX = APP_DIR / "jmeter" / "bitbucket.jmx" JSM_JMX_AGENTS = APP_DIR / "jmeter" / "jsm_agents.jmx" @@ -35,7 +38,8 @@ DEFAULT_HOSTNAMES = ['test_jira_instance.atlassian.com', 'test_confluence_instance.atlassian.com', 'test_bitbucket_instance.atlassian.com', - 'test_jsm_instance.atlassian.com'] + 'test_jsm_instance.atlassian.com', + 'test_crowd_instance.atlassian.com'] AGENTS = "agents" CUSTOMERS = "customers" @@ -60,6 +64,9 @@ def __init__(self): elif self.args.app == BITBUCKET: self.yml = BITBUCKET_YML self.jmx = BITBUCKET_JMX + elif self.args.app == CROWD: + self.yml = CROWD_YML + self.jmx = CROWD_JMX elif self.args.app == JSM: if not self.args.type: raise SystemExit('JSM user type is not specified. e.g. --type agents/customers') diff --git a/app/util/jtl_convertor/jtls-to-csv.py b/app/util/jtl_convertor/jtls-to-csv.py index f5416da9b..0387e6160 100644 --- a/app/util/jtl_convertor/jtls-to-csv.py +++ b/app/util/jtl_convertor/jtls-to-csv.py @@ -32,7 +32,7 @@ CSV_HEADER = f'{LABEL},{SAMPLES},{AVERAGE},{MEDIAN},{PERC_90},{PERC_95},{PERC_99},{MIN},{MAX},{ERROR_RATE},' \ f'{APP_SPECIFIC}\n' RESULTS_CSV_NAME = 'results.csv' -APPS = ['jira', 'confluence', 'bitbucket', 'jsm'] +APPS = ['jira', 'confluence', 'bitbucket', 'jsm', 'crowd'] TEST_TYPES = ['selenium', 'jmeter', 'locust'] diff --git a/app/util/project_paths.py b/app/util/project_paths.py index afa9bb21a..ac3c0f159 100644 --- a/app/util/project_paths.py +++ b/app/util/project_paths.py @@ -43,6 +43,18 @@ def __get_bitbucket_datasets(): return __get_datasets() / "bitbucket" +def __get_crowd_yml(): + return Path(__file__).parents[1] / "crowd.yml" + + +def __get_crowd_datasets(): + return __get_datasets() / "crowd" + + +def __get_crowd_dataset(file_name): + return __get_crowd_datasets() / file_name + + def __get_confluence_datasets(): return __get_datasets() / "confluence" @@ -105,5 +117,10 @@ def __get_default_test_actions(): BITBUCKET_REPOS = __get_bitbucket_dataset('repos.csv') BITBUCKET_PRS = __get_bitbucket_dataset('pull_requests.csv') +CROWD_YML = __get_crowd_yml() +CROWD_DATASETS = __get_crowd_datasets() +CROWD_USERS = __get_crowd_dataset('users.csv') + + DEFAULT_TEST_ACTIONS = __get_default_test_actions() ENV_TAURUS_ARTIFACT_DIR = __get_taurus_artifacts_dir() diff --git a/docs/crowd/README.md b/docs/crowd/README.md new file mode 100644 index 000000000..b8aeb2b16 --- /dev/null +++ b/docs/crowd/README.md @@ -0,0 +1,77 @@ +# User Guide for Crowd +https://developer.atlassian.com/platform/marketplace/dc-apps-performance-toolkit-user-guide-crowd/ + +# Running tests +## Pre-requisites +* Working Crowd Software of supported version ([toolkit README](../../README.md) for a list of supported Crowd versions) with users, groups, etc. +* Client machine with 4 CPUs and 16 GBs of RAM to run the Toolkit. +* Virtual environment with Python and bzt installed. See the root [toolkit README](../../README.md) file for more details. + +If you need performance testing results at a production level, follow instructions described +in the official User Guide to set up Crowd DC with the corresponding dataset. +For spiking, testing, or developing, your local Crowd instance would work well. + +## Step 1: Update crowd.yml +* `application_hostname`: test crowd hostname (without http). +* `application_protocol`: http or https. +* `application_port`: 80 (for http) or 443 (for https), 8080, 4990 or your instance-specific port. +* `secure`: True or False. Default value is True. Set False to allow insecure connections, e.g. when using self-signed SSL certificate. +* `application_postfix`: it is empty by default; e.g., /crowd for url like this http://localhost:4990/crowd. +* `admin_login`: crowd admin username (after restoring dataset from SQL dump, the admin user name is: admin). +* `admin_password`: crowd admin user password (after restoring dataset from SQL dump, the admin user password is: admin) . +* `application_name`: name of crowd application. +* `application_password`: password of crowd application. +* `load_executor`: `jmeter`. +* `concurrency`: `1000` - number of concurrent users for JMeter scenario. +* `test_duration`: `45m` - duration of test execution. + +## Step 2: Run tests +Run Taurus. +``` +bzt crowd.yml +``` + +## Results +Results are located in the `resutls/crowd/YY-MM-DD-hh-mm-ss` directory: +* `bzt.log` - log of bzt run +* `error_artifacts` - folder with screenshots and HTMLs of Selenium fails +* `jmeter.err` - JMeter errors log +* `kpi.jtl` - JMeter raw data +* `results.csv` - consolidated results of execution +* `resutls_summary.log` - detailed summary of the run. Make sure that overall run status is `OK` before moving to the +next steps. + + +# Useful information + +## Changing performance workload for JMeter +The [crowd.yml](../../app/crowd.yml) has three pairs of parameters for different workload depends on crowd instance nodes count. +``` + # 1 node scenario parameters + ramp-up: 20s # time to spin all concurrent threads + total_actions_per_hour: 180000 # number of total JMeter actions per hour + + # 2 nodes scenario parameters + # ramp-up: 10s # time to spin all concurrent threads + # total_actions_per_hour: 360000 # number of total JMeter actions per hour + + # 4 nodes scenario parameters + # ramp-up: 5s # time to spin all concurrent threads + # total_actions_per_hour: 720000 # number of total JMeter actions per hour + ``` +Uncomment appropriate part of configs to produce necessary instance workload. +For app-specific actions development and testing it's ok to reduce concurrency, test_duration, total_actions_per_hour and ramp-up. + +## JMeter +### Debugging JMeter scripts +1. Open JMeter UI as described in [README.md](../../app/util/jmeter/README.md). +1. On the `View Results Tree` controller, click the `Browse` button and open `error.jtl` from `app/results/crowd/YY-MM-DD-hh-mm-ss` folder. + +From this view, you can click on any failed action and see the request and response data in appropriate tabs. + +### Run JMeter actions via GUI +1. Open JMeter UI as described in [README.md](../../app/util/jmeter/README.md). +1. Enable the `View Results Tree` controller and click `Run` the test scenario. + +### Comparing different runs +Navigate to the `reports_generation` folder and follow README.md instructions to generate side-by-side comparison charts. diff --git a/docs/dc-apps-performance-toolkit-user-guide-bitbucket.md b/docs/dc-apps-performance-toolkit-user-guide-bitbucket.md index 05065d679..594098091 100644 --- a/docs/dc-apps-performance-toolkit-user-guide-bitbucket.md +++ b/docs/dc-apps-performance-toolkit-user-guide-bitbucket.md @@ -4,7 +4,7 @@ platform: platform product: marketplace category: devguide subcategory: build -date: "2021-04-26" +date: "2021-06-16" --- # Data Center App Performance Toolkit User Guide For Bitbucket @@ -99,7 +99,7 @@ All important parameters are listed and described in this section. For all other | Parameter | Recommended Value | | --------- | ----------------- | -| Version | The Data Center App Performance Toolkit officially supports `7.6.4`, `6.10.9` ([Long Term Support releases](https://confluence.atlassian.com/enterprise/atlassian-enterprise-releases-948227420.html)) and `7.0.5` Platform Release | +| Version | The Data Center App Performance Toolkit officially supports `7.6.7`, `6.10.11` ([Long Term Support releases](https://confluence.atlassian.com/enterprise/atlassian-enterprise-releases-948227420.html)) and `7.0.5` Platform Release | **Cluster nodes** @@ -242,8 +242,9 @@ To populate the database with SQL: ssh-add path_to_your_private_key_pem export BASTION_IP=bastion_instance_public_ip export NODE_IP=node_private_ip - export SSH_OPTS='-o ServerAliveInterval=60 -o ServerAliveCountMax=30' - ssh ${SSH_OPTS} -o "proxycommand ssh -W %h:%p ${SSH_OPTS} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} + export SSH_OPTS1='-o ServerAliveInterval=60' + export SSH_OPTS2='-o ServerAliveCountMax=30' + ssh ${SSH_OPTS1} ${SSH_OPTS2} -o "proxycommand ssh -W %h:%p ${SSH_OPTS1} ${SSH_OPTS2} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} ``` For more information, go to [Connecting your nodes over SSH](https://confluence.atlassian.com/adminjiraserver/administering-jira-data-center-on-aws-938846969.html#AdministeringJiraDataCenteronAWS-ConnectingtoyournodesoverSSH). 1. Stop Bitbucket Server: @@ -259,8 +260,9 @@ To populate the database with SQL: ssh-add path_to_your_private_key_pem export BASTION_IP=bastion_instance_public_ip export NFS_SERVER_IP=nfs_server_private_ip - export SSH_OPTS='-o ServerAliveInterval=60 -o ServerAliveCountMax=30' - ssh ${SSH_OPTS} -o "proxycommand ssh -W %h:%p ${SSH_OPTS} ec2-user@${BASTION_IP}" ec2-user@${NFS_SERVER_IP} + export SSH_OPTS1='-o ServerAliveInterval=60' + export SSH_OPTS2='-o ServerAliveCountMax=30' + ssh ${SSH_OPTS1} ${SSH_OPTS2} -o "proxycommand ssh -W %h:%p ${SSH_OPTS1} ${SSH_OPTS2} ec2-user@${BASTION_IP}" ec2-user@${NFS_SERVER_IP} ``` For more information, go to [Connecting your nodes over SSH](https://confluence.atlassian.com/adminjiraserver/administering-jira-data-center-on-aws-938846969.html#AdministeringJiraDataCenteronAWS-ConnectingtoyournodesoverSSH). @@ -315,8 +317,9 @@ Populate DB and restore attachments scripts could be run in parallel in separate ssh-add path_to_your_private_key_pem export BASTION_IP=bastion_instance_public_ip export NFS_SERVER_IP=nfs_server_private_ip - export SSH_OPTS='-o ServerAliveInterval=60 -o ServerAliveCountMax=30' - ssh ${SSH_OPTS} -o "proxycommand ssh -W %h:%p ${SSH_OPTS} ec2-user@$BASTION_IP" ec2-user@${NFS_SERVER_IP} + export SSH_OPTS1='-o ServerAliveInterval=60' + export SSH_OPTS2='-o ServerAliveCountMax=30' + ssh ${SSH_OPTS1} ${SSH_OPTS2} -o "proxycommand ssh -W %h:%p ${SSH_OPTS1} ${SSH_OPTS2} ec2-user@$BASTION_IP" ec2-user@${NFS_SERVER_IP} ``` For more information, go to [Connecting your nodes over SSH](https://confluence.atlassian.com/adminjiraserver/administering-jira-data-center-on-aws-938846969.html#AdministeringJiraDataCenteronAWS-ConnectingtoyournodesoverSSH). 1. Download the [upload_attachments.sh](https://github.com/atlassian/dc-app-performance-toolkit/blob/master/app/util/bitbucket/upload_attachments.sh) script and make it executable: @@ -354,8 +357,9 @@ Do not close or interrupt the session. It will take about two hours to upload at ssh-add path_to_your_private_key_pem export BASTION_IP=bastion_instance_public_ip export NODE_IP=node_private_ip - export SSH_OPTS='-o ServerAliveInterval=60 -o ServerAliveCountMax=30' - ssh ${SSH_OPTS} -o "proxycommand ssh -W %h:%p ${SSH_OPTS} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} + export SSH_OPTS1='-o ServerAliveInterval=60' + export SSH_OPTS2='-o ServerAliveCountMax=30' + ssh ${SSH_OPTS1} ${SSH_OPTS2} -o "proxycommand ssh -W %h:%p ${SSH_OPTS1} ${SSH_OPTS2} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} ``` For more information, go to [Connecting your nodes over SSH](https://confluence.atlassian.com/adminjiraserver/administering-jira-data-center-on-aws-938846969.html#AdministeringJiraDataCenteronAWS-ConnectingtoyournodesoverSSH). 1. Start Bitbucket DC: @@ -392,7 +396,7 @@ In case of any difficulties with Index generation, contact us for support in the For generating performance results suitable for Marketplace approval process use dedicated execution environment. This is a separate AWS EC2 instance to run the toolkit from. Running the toolkit from a dedicated instance but not from a local machine eliminates network fluctuations and guarantees stable CPU and memory performance. 1. Go to GitHub and create a fork of [dc-app-performance-toolkit](https://github.com/atlassian/dc-app-performance-toolkit). -1. Clone the fork locally, then edit the `bitbucket.yml` configuration file. Set enterprise-scale Jira Data Center parameters: +1. Clone the fork locally, then edit the `bitbucket.yml` configuration file. Set enterprise-scale Bitbucket Data Center parameters: ``` yaml application_hostname: test_bitbucket_instance.atlassian.com # Bitbucket DC hostname without protocol and port e.g. test-bitbucket.atlassian.com or localhost @@ -461,7 +465,7 @@ To receive performance baseline results **without** an app installed: docker run --shm-size=4g -v "$PWD:/dc-app-performance-toolkit" atlassian/dcapt bitbucket.yml ``` -1. View the following main results of the run in the `dc-app-performance-toolkit/app/results/jira/YY-MM-DD-hh-mm-ss` folder: +1. View the following main results of the run in the `dc-app-performance-toolkit/app/results/bitbucket/YY-MM-DD-hh-mm-ss` folder: - `results_summary.log`: detailed run summary - `results.csv`: aggregated .csv file with all actions and timings - `bzt.log`: logs of the Taurus tool execution @@ -520,7 +524,7 @@ Use [scp](https://man7.org/linux/man-pages/man1/scp.1.html) command to copy repo 1. From local machine terminal (Git bash terminal for Windows) run command: ``` bash export EXEC_ENV_PUBLIC_IP=execution_environment_ec2_instance_public_ip - scp -r -i path_to_exec_env_pem ubuntu@EXEC_ENV_PUBLIC_IP:/home/ubuntu/dc-app-performance-toolkit/app/results/reports ./reports + scp -r -i path_to_exec_env_pem ubuntu@$EXEC_ENV_PUBLIC_IP:/home/ubuntu/dc-app-performance-toolkit/app/results/reports ./reports ``` 1. Once completed, in the `./reports` folder you will be able to review the action timings with and without your app to see its impact on the performance of the instance. If you see an impact (>20%) on any action timing, we recommend taking a look into the app implementation to understand the root cause of this delta. @@ -532,6 +536,7 @@ For many apps and extensions to Atlassian products, there should not be a signif #### Extending the base action +You can find more info about the local Bitbucket setup for developer's purpose in the [README.md](https://github.com/atlassian/dc-app-performance-toolkit/blob/master/README.md) file. Extension scripts, which extend the base Selenium (`bitbucket-ui.py`) scripts, are located in a separate folder (`dc-app-performance-toolkit/extension/bitbucket`). You can modify these scripts to include their app-specific actions. ##### Modifying Selenium @@ -639,9 +644,9 @@ To generate a scalability report: ``` 1. Navigate to the `dc-app-performance-toolkit/app/reports_generation` folder. 1. Edit the `scale_profile.yml` file: - - For `runName: "Node 1"`, in the `fullPath` key, insert the full path to results directory of [Run 3](#run3). - - For `runName: "Node 2"`, in the `fullPath` key, insert the full path to results directory of [Run 4](#run4). - - For `runName: "Node 4"`, in the `fullPath` key, insert the full path to results directory of [Run 5](#run5). + - For `runName: "1 Node"`, in the `fullPath` key, insert the full path to results directory of [Run 3](#run3). + - For `runName: "2 Nodes"`, in the `fullPath` key, insert the full path to results directory of [Run 4](#run4). + - For `runName: "4 Nodes"`, in the `fullPath` key, insert the full path to results directory of [Run 5](#run5). 1. Run the following command from the `virtualenv` (as described in `dc-app-performance-toolkit/README.md`): ``` bash python csv_chart_generator.py scale_profile.yml @@ -656,9 +661,9 @@ Use [scp](https://man7.org/linux/man-pages/man1/scp.1.html) command to copy repo 1. From local terminal (Git bash terminal for Windows) run command: ``` bash export EXEC_ENV_PUBLIC_IP=execution_environment_ec2_instance_public_ip - scp -r -i path_to_exec_env_pem ubuntu@EXEC_ENV_PUBLIC_IP:/home/ubuntu/dc-app-performance-toolkit/app/results/reports ./reports + scp -r -i path_to_exec_env_pem ubuntu@$EXEC_ENV_PUBLIC_IP:/home/ubuntu/dc-app-performance-toolkit/app/results/reports ./reports ``` -1. Once completed, in the `./reports` folder you will be able to review action timings on Jira Data Center with different numbers of nodes. If you see a significant variation in any action timings between configurations, we recommend taking a look into the app implementation to understand the root cause of this delta. +1. Once completed, in the `./reports` folder you will be able to review action timings on Bitbucket Data Center with different numbers of nodes. If you see a significant variation in any action timings between configurations, we recommend taking a look into the app implementation to understand the root cause of this delta. {{% warning %}} After completing all your tests, delete your Bitbucket Data Center stacks. diff --git a/docs/dc-apps-performance-toolkit-user-guide-confluence.md b/docs/dc-apps-performance-toolkit-user-guide-confluence.md index dc3202918..d9777b177 100644 --- a/docs/dc-apps-performance-toolkit-user-guide-confluence.md +++ b/docs/dc-apps-performance-toolkit-user-guide-confluence.md @@ -4,7 +4,7 @@ platform: platform product: marketplace category: devguide subcategory: build -date: "2021-04-26" +date: "2021-06-16" --- # Data Center App Performance Toolkit User Guide For Confluence @@ -66,7 +66,7 @@ All important parameters are listed and described in this section. For all other | Parameter | Recommended value | | --------- | ----------------- | | Collaborative editing mode | synchrony-local | -| Confluence Version | The Data Center App Performance Toolkit officially supports `7.4.8` ([Long Term Support release](https://confluence.atlassian.com/enterprise/atlassian-enterprise-releases-948227420.html)) and `7.0.5` Platform Release | +| Confluence Version | The Data Center App Performance Toolkit officially supports `7.4.9` ([Long Term Support release](https://confluence.atlassian.com/enterprise/atlassian-enterprise-releases-948227420.html)) and `7.0.5` Platform Release | **Cluster nodes** @@ -249,7 +249,7 @@ You develop an app that introduces new GET and POST endpoints in Confluence Data 1. Extend example of app-specific action in `dc-app-performance-toolkit/app/extension/confluence/extension_locust.py`, so that test will call the endpoint with GET request, parse response use these data to call another endpoint with POST request and measure response time. [Code example.](https://github.com/atlassian/dc-app-performance-toolkit/blob/master/app/extension/confluence/extension_locust.py) 1. In `dc-app-performance-toolkit/app/confluence.yml` set `load_executor: locust` to make `locust` as load executor. -1. Locust uses actions percentage as relative [weights](https://docs.locust.io/en/stable/writing-a-locustfile.html#weight-attribute), so if `some_action: 10` and `standalone_extension: 20` that means that `standalone_extension` will be called twice more. +1. Set desired execution percentage for `standalone_extension`. Default value is `0`, which means that `standalone_extension` action will not be executed. Locust uses actions percentage as relative [weights](https://docs.locust.io/en/stable/writing-a-locustfile.html#weight-attribute), so if `some_action: 10` and `standalone_extension: 20` that means that `standalone_extension` will be called twice more. Set `standalone_extension` weight in accordance with the expected frequency of your app use case compared with other base actions. 1. App-specific tests could be run (if needed) as a specific user. Use `@run_as_specific_user(username='specific_user_username', password='specific_user_password')` decorator for that. 1. Run toolkit with `bzt confluence.yml` command to ensure that all Locust actions including `app_specific_action` are successful. @@ -380,7 +380,7 @@ All important parameters are listed and described in this section. For all other | Parameter | Recommended value | | --------- | ----------------- | | Collaborative editing mode | synchrony-local | -| Confluence Version | The Data Center App Performance Toolkit officially supports `7.4.8` ([Long Term Support release](https://confluence.atlassian.com/enterprise/atlassian-enterprise-releases-948227420.html)) and `7.0.5` Platform Release | +| Confluence Version | The Data Center App Performance Toolkit officially supports `7.4.9` ([Long Term Support release](https://confluence.atlassian.com/enterprise/atlassian-enterprise-releases-948227420.html)) and `7.0.5` Platform Release | **Cluster nodes** @@ -515,8 +515,9 @@ To populate the database with SQL: ssh-add path_to_your_private_key_pem export BASTION_IP=bastion_instance_public_ip export NODE_IP=node_private_ip - export SSH_OPTS='-o ServerAliveInterval=60 -o ServerAliveCountMax=30' - ssh ${SSH_OPTS} -o "proxycommand ssh -W %h:%p ${SSH_OPTS} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} + export SSH_OPTS1='-o ServerAliveInterval=60' + export SSH_OPTS2='-o ServerAliveCountMax=30' + ssh ${SSH_OPTS1} ${SSH_OPTS2} -o "proxycommand ssh -W %h:%p ${SSH_OPTS1} ${SSH_OPTS2} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} ``` For more information, go to [Connecting your nodes over SSH](https://confluence.atlassian.com/adminjiraserver/administering-jira-data-center-on-aws-938846969.html#AdministeringJiraDataCenteronAWS-ConnectingtoyournodesoverSSH). 1. Download the [populate_db.sh](https://github.com/atlassian/dc-app-performance-toolkit/blob/master/app/util/confluence/populate_db.sh) script and make it executable: @@ -563,8 +564,9 @@ Populate DB and restore attachments scripts could be run in parallel in separate ssh-add path_to_your_private_key_pem export BASTION_IP=bastion_instance_public_ip export NODE_IP=node_private_ip - export SSH_OPTS='-o ServerAliveInterval=60 -o ServerAliveCountMax=30' - ssh ${SSH_OPTS} -o "proxycommand ssh -W %h:%p ${SSH_OPTS} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} + export SSH_OPTS1='-o ServerAliveInterval=60' + export SSH_OPTS2='-o ServerAliveCountMax=30' + ssh ${SSH_OPTS1} ${SSH_OPTS2} -o "proxycommand ssh -W %h:%p ${SSH_OPTS1} ${SSH_OPTS2} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} ``` For more information, go to [Connecting your nodes over SSH](https://confluence.atlassian.com/adminjiraserver/administering-jira-data-center-on-aws-938846969.html#AdministeringJiraDataCenteronAWS-ConnectingtoyournodesoverSSH). 1. Download the [upload_attachments.sh](https://github.com/atlassian/dc-app-performance-toolkit/blob/master/app/util/confluence/upload_attachments.sh) script and make it executable: @@ -620,8 +622,9 @@ For more information, go to [Administer your Data Center search index](https://c ssh-add path_to_your_private_key_pem export BASTION_IP=bastion_instance_public_ip export NODE_IP=node_private_ip - export SSH_OPTS='-o ServerAliveInterval=60 -o ServerAliveCountMax=30' - ssh ${SSH_OPTS} -o "proxycommand ssh -W %h:%p ${SSH_OPTS} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} + export SSH_OPTS1='-o ServerAliveInterval=60' + export SSH_OPTS2='-o ServerAliveCountMax=30' + ssh ${SSH_OPTS1} ${SSH_OPTS2} -o "proxycommand ssh -W %h:%p ${SSH_OPTS1} ${SSH_OPTS2} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} ``` 1. Download the [index-snapshot.sh](https://raw.githubusercontent.com/atlassian/dc-app-performance-toolkit/master/app/util/confluence/index-snapshot.sh) file. Then, make it executable and run it: @@ -761,7 +764,7 @@ Use [scp](https://man7.org/linux/man-pages/man1/scp.1.html) command to copy repo 1. From local machine terminal (Git bash terminal for Windows) run command: ``` bash export EXEC_ENV_PUBLIC_IP=execution_environment_ec2_instance_public_ip - scp -r -i path_to_exec_env_pem ubuntu@EXEC_ENV_PUBLIC_IP:/home/ubuntu/dc-app-performance-toolkit/app/results/reports ./reports + scp -r -i path_to_exec_env_pem ubuntu@$EXEC_ENV_PUBLIC_IP:/home/ubuntu/dc-app-performance-toolkit/app/results/reports ./reports ``` 1. Once completed, in the `./reports` folder you will be able to review the action timings with and without your app to see its impact on the performance of the instance. If you see an impact (>20%) on any action timing, we recommend taking a look into the app implementation to understand the root cause of this delta. @@ -812,8 +815,9 @@ To receive scalability benchmark results for two-node Confluence DC **with** app ssh-add path_to_your_private_key_pem export BASTION_IP=bastion_instance_public_ip export NODE_IP=node_private_ip - export SSH_OPTS='-o ServerAliveInterval=60 -o ServerAliveCountMax=30' - ssh ${SSH_OPTS} -o "proxycommand ssh -W %h:%p ${SSH_OPTS} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} + export SSH_OPTS1='-o ServerAliveInterval=60' + export SSH_OPTS2='-o ServerAliveCountMax=30' + ssh ${SSH_OPTS1} ${SSH_OPTS2} -o "proxycommand ssh -W %h:%p ${SSH_OPTS1} ${SSH_OPTS2} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} ``` 1. Once you're in the second node, download the [index-sync.sh](https://raw.githubusercontent.com/atlassian/dc-app-performance-toolkit/master/app/util/confluence/index-sync.sh) file. Then, make it executable and run it: @@ -878,9 +882,9 @@ To generate a scalability report: ``` 1. Navigate to the `dc-app-performance-toolkit/app/reports_generation` folder. 1. Edit the `scale_profile.yml` file: - - For `runName: "Node 1"`, in the `fullPath` key, insert the full path to results directory of [Run 3](#run3). - - For `runName: "Node 2"`, in the `fullPath` key, insert the full path to results directory of [Run 4](#run4). - - For `runName: "Node 4"`, in the `fullPath` key, insert the full path to results directory of [Run 5](#run5). + - For `runName: "1 Node"`, in the `fullPath` key, insert the full path to results directory of [Run 3](#run3). + - For `runName: "2 Nodes"`, in the `fullPath` key, insert the full path to results directory of [Run 4](#run4). + - For `runName: "4 Nodes"`, in the `fullPath` key, insert the full path to results directory of [Run 5](#run5). 1. Run the following command from the `virtualenv` (as described in `dc-app-performance-toolkit/README.md`): ``` bash python csv_chart_generator.py scale_profile.yml @@ -895,7 +899,7 @@ Use [scp](https://man7.org/linux/man-pages/man1/scp.1.html) command to copy repo 1. From local terminal (Git bash terminal for Windows) run command: ``` bash export EXEC_ENV_PUBLIC_IP=execution_environment_ec2_instance_public_ip - scp -r -i path_to_exec_env_pem ubuntu@EXEC_ENV_PUBLIC_IP:/home/ubuntu/dc-app-performance-toolkit/app/results/reports ./reports + scp -r -i path_to_exec_env_pem ubuntu@$EXEC_ENV_PUBLIC_IP:/home/ubuntu/dc-app-performance-toolkit/app/results/reports ./reports ``` 1. Once completed, in the `./reports` folder, you will be able to review action timings on Confluence Data Center with different numbers of nodes. If you see a significant variation in any action timings between configurations, we recommend taking a look into the app implementation to understand the root cause of this delta. diff --git a/docs/dc-apps-performance-toolkit-user-guide-crowd.md b/docs/dc-apps-performance-toolkit-user-guide-crowd.md new file mode 100644 index 000000000..87e6f737d --- /dev/null +++ b/docs/dc-apps-performance-toolkit-user-guide-crowd.md @@ -0,0 +1,591 @@ +--- +title: "Data Center App Performance Toolkit User Guide For Crowd" +platform: platform +product: marketplace +category: devguide +subcategory: build +date: "2021-06-16" +--- +# Data Center App Performance Toolkit User Guide For Crowd + +This document walks you through the process of testing your app on Crowd using the Data Center App Performance Toolkit. These instructions focus on producing the required [performance and scale benchmarks for your Data Center app](https://developer.atlassian.com/platform/marketplace/dc-apps-performance-and-scale-testing/). + +In this document, we cover the use of the Data Center App Performance Toolkit on Enterprise-scale environment. + +**Enterprise-scale environment**: Crowd Data Center environment used to generate Data Center App Performance Toolkit test results for the Marketplace approval process. Preferably, use the [AWS Quick Start for Crowd Data Center](https://aws.amazon.com/quickstart/architecture/atlassian-crowd) with the parameters prescribed below. These parameters provision larger, more powerful infrastructure for your Crowd Data Center. + +1. [Set up an enterprise-scale environment Crowd Data Center on AWS](#instancesetup). +2. [Load an enterprise-scale dataset on your Crowd Data Center deployment](#preloading). +3. [App-specific actions development](#appspecificaction). +4. [Set up an execution environment for the toolkit](#executionhost). +5. [Running the test scenarios from execution environment against enterprise-scale Crowd Data Center](#testscenario). + +--- + +## <a id="instancesetup"></a>1. Set up an enterprise-scale environment Crowd Data Center on AWS + +We recommend that you use the [AWS Quick Start for Crowd Data Center](https://aws.amazon.com/quickstart/architecture/atlassian-crowd) (**How to deploy** tab) to deploy a Crowd Data Center enterprise-scale environment. This Quick Start will allow you to deploy Crowd Data Center with a new [Atlassian Standard Infrastructure](https://aws.amazon.com/quickstart/architecture/atlassian-standard-infrastructure/) (ASI) or into an existing one. + +The ASI is a Virtual Private Cloud (VPC) consisting of subnets, NAT gateways, security groups, bastion hosts, and other infrastructure components required by all Atlassian applications, and then deploys Crowd into this new VPC. Deploying Crowd with a new ASI takes around 50 minutes. With an existing one, it'll take around 30 minutes. + +#### Using the AWS Quick Start for Crowd + +If you are a new user, perform an end-to-end deployment. This involves deploying Crowd into a _new_ ASI: + +Navigate to **[AWS Quick Start for Crowd Data Center](https://aws.amazon.com/quickstart/architecture/atlassian-crowd/) > How to deploy** tab **> Deploy into a new ASI** link. + +If you have already deployed the ASI separately by using the [ASI Quick Start](https://aws.amazon.com/quickstart/architecture/atlassian-standard-infrastructure/)ASI Quick Start or by deploying another Atlassian product (Jira, Bitbucket, Confluence or Crowd Data Center development environment) with ASI, deploy Crowd into your existing ASI: + +Navigate to **[AWS Quick Start for Crowd Data Center](https://aws.amazon.com/quickstart/architecture/atlassian-crowd) > How to deploy** tab **> Deploy into your existing ASI** link. + +{{% note %}} +You are responsible for the cost of the AWS services used while running this Quick Start reference deployment. There is no additional price for using this Quick Start. For more information, go to [aws.amazon.com/pricing](https://aws.amazon.com/ec2/pricing/). +{{% /note %}} + +To reduce costs, we recommend you to keep your deployment up and running only during the performance runs. + +#### AWS cost estimation +[AWS Pricing Calculator](https://calculator.aws/) provides an estimate of usage charges for AWS services based on certain information you provide. +Monthly charges will be based on your actual usage of AWS services and may vary from the estimates the Calculator has provided. + +*The prices below are approximate and may vary depending on such factors like region, instance type, deployment type of DB, and other. + + +| Stack | Estimated hourly cost ($) | +| ----- | ------------------------- | +| One Node Crowd DC | 0.4 - 0.6 +| Two Nodes Crowd DC | 0.6 - 0.8 +| Four Nodes Crowd DC | 0.9 - 1.4 + +#### Stop cluster nodes + +To reduce AWS infrastructure costs you could stop cluster nodes when the cluster is standing idle. +Cluster node might be stopped by using [Suspending and Resuming Scaling Processes](https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-suspend-resume-processes.html). + +To stop one node within the cluster, follow the instructions below: + +1. In the AWS console, go to **Services** > **EC2** > **Auto Scaling Groups** and open the necessary group to which belongs the node you want to stop. +1. Click **Edit** (in case you have New EC2 experience UI mode enabled, press `Edit` on `Advanced configuration`) and add `HealthCheck` to the `Suspended Processes`. Amazon EC2 Auto Scaling stops marking instances unhealthy as a result of EC2 and Elastic Load Balancing health checks. +1. Go to EC2 **Instances**, select instance, click **Instance state** > **Stop instance**. + +To return node into a working state follow the instructions: + +1. Go to EC2 **Instances**, select instance, click **Instance state** > **Start instance**, wait a few minutes for node to become available. +1. Go to EC2 **Auto Scaling Groups** and open the necessary group to which belongs the node you want to start. +1. Press **Edit** (in case you have New EC2 experience UI mode enabled, press `Edit` on `Advanced configuration`) and remove `HealthCheck` from `Suspended Processes` of Auto Scaling Group. + +#### Stop database + +To reduce AWS infrastructure costs database could be stopped when the cluster is standing idle. +Keep in mind that database would be **automatically started** in **7** days. + +To stop database: + +1. In the AWS console, go to **Services** > **RDS** > **Databases**. +1. Select cluster database. +1. Click on **Actions** > **Stop**. + +To start database: + +1. In the AWS console, go to **Services** > **RDS** > **Databases**. +1. Select cluster database. +1. Click on **Actions** > **Start**. + +#### <a id="quick-start-parameters"></a> Quick Start parameters + +All important parameters are listed and described in this section. For all other remaining parameters, we recommend using the Quick Start defaults. + +**Crowd setup** + +| Parameter | Recommended Value | +| --------- | ----------------- | +| Version | The Data Center App Performance Toolkit officially supports `4.3.0` ([Long Term Support release](https://confluence.atlassian.com/crowd/crowd-release-notes-199094.html)) | + +**Cluster nodes** + +| Parameter | Recommended Value | +| --------- | ----------------- | +| Cluster node instance type | [c5.xlarge](https://aws.amazon.com/ec2/instance-types/c5/) +| Maximum number of cluster nodes | 1 | +| Minimum number of cluster nodes | 1 | +| Cluster node instance volume size | 100 | + +**Database** + +| Parameter | Recommended Value | +| --------- | ----------------- | +| The database engine to deploy with | PostgresSQL | +| The database engine version to use | 11 | +| Database instance class | [db.m5.large](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.DBInstanceClass.html#Concepts.DBInstanceClass.Summary) | +| RDS Provisioned IOPS | 1000 | +| Master (admin) password | Password1! | +| Enable RDS Multi-AZ deployment | false | +| Application user database password | Password1! | +| Database storage | 200 | + +{{% note %}} +The **Master (admin) password** will be used later when restoring the SQL database dataset. If password value is not set to default, you'll need to change `DB_PASS` value manually in the restore database dump script (later in [Preloading your Crowd deployment with an enterprise-scale dataset](#preloading)). +{{% /note %}} + +**Networking (for new ASI)** + +| Parameter | Recommended Value | +| --------- | ----------------- | +| Trusted IP range | 0.0.0.0/0 _(for public access) or your own trusted IP range_ | +| Availability Zones | _Select two availability zones in your region_ | +| Permitted IP range | 0.0.0.0/0 _(for public access) or your own trusted IP range_ | +| Make instance internet facing | true | +| Key Name | _The EC2 Key Pair to allow SSH access. See [Amazon EC2 Key Pairs](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html) for more info._ | + +**Networking (for existing ASI)** + +| Parameter | Recommended Value | +| --------- | ----------------- | +| Make instance internet facing | true | +| Permitted IP range | 0.0.0.0/0 _(for public access) or your own trusted IP range_ | +| Key Name | _The EC2 Key Pair to allow SSH access. See [Amazon EC2 Key Pairs](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html) for more info._ | + +#### Running the setup wizard + +After successfully deploying Crowd Data Center in AWS, you'll need to configure it: + +1. In the AWS console, go to **Services** > **CloudFormation** > **Stack** > **Stack details** > **Select your stack**. +1. On the **Outputs** tab, copy the value of the **LoadBalancerURL** key. +1. Open **LoadBalancerURL** in your browser. This will take you to the Crowd setup wizard. +1. On the **License** page, populate the **License Key** field by either: + - Using your existing license, or + - Generating a Crowd trial license, or + - Contacting Atlassian to be provided two time-bomb licenses for testing. + Click **Continue**. +1. On the **Crowd installation** page choose **New Installation** and click **Continue**. +1. On the **Database configuration** page, leave all fields default and click **Continue**. +1. On the **Options** page, populate the following fields: + - **Deployment title**: any instance title + - **Session timeout**: 30 _(recommended)_. The number of minutes a session lasts before expiring. Must be greater than 0. + - **Base Url**: review and confirm the Crowd instance base url. + Click **Continue**. +1. On the **Internal directory** page, populate the following fields and press **Continue**: + - **Name**: a short, recognisable name that characterises this user directory. + - **Password encryption**: chose **ATLASSIAN-SECURITY** from the dropdown list _(recommended)_ + Click **Continue**. +1. On the **Default administrator** page, fill the following fields: + - **Email Address**: email address of the admin user + - **Username**: admin _(recommended)_ + - **Password**: admin _(recommended)_ + - **Confirm Password**: admin _(recommended)_ + - **First name**: admin user first name + - **Last name**: admin user last name + Click **Continue**. +1. On the **Integrated applications** page leave **Open ID server** unchecked and click **Continue**. + +{{% note %}} +After [Preloading your Crowd deployment with an enterprise-scale dataset](#preloading), the admin user will have `admin`/`admin` credentials. +{{% /note %}} + +--- + +## <a id="preloading"></a>2. Preloading your Crowd deployment with an enterprise-scale dataset + +Data dimensions and values for an enterprise-scale dataset are listed and described in the following table. + +| Data dimensions | Value for an enterprise-scale dataset | +| --------------- | ------------------------------------- | +| Users | ~100 000 | +| Groups | ~15 | + +{{% note %}} +All the datasets use the standard `admin`/`admin` credentials. +{{% /note %}} + +#### Pre-loading the dataset: + +[Importing the main dataset](#importingdataset). To help you out, we provide an enterprise-scale dataset you can import either via the [populate_db.sh](https://github.com/atlassian/dc-app-performance-toolkit/blob/master/app/util/crowd/populate_db.sh) script or restore from xml backup file. + +The following subsections explain dataset import process in greater detail. + +#### <a id="importingdataset"></a> Importing the main dataset + +You can load this dataset directly into the database (via a [populate_db.sh](https://github.com/atlassian/dc-app-performance-toolkit/blob/master/app/util/crowd/populate_db.sh) script), or import it via XML. + +##### Option 1 (recommended): Loading the dataset via populate_db.sh script (~15 minutes) + + +To populate the database with SQL: + +1. In the AWS console, go to **Services** > **EC2** > **Instances**. +1. On the **Description** tab, do the following: + - Copy the _Public IP_ of the Bastion instance. + - Copy the _Private IP_ of the Crowd node instance. +1. Using SSH, connect to the Crowd node via the Bastion instance: + + For Linux or MacOS run following commands in terminal (for Windows use [Git Bash](https://git-scm.com/downloads) terminal): + + ```bash + ssh-add path_to_your_private_key_pem + export BASTION_IP=bastion_instance_public_ip + export NODE_IP=node_private_ip + export SSH_OPTS1='-o ServerAliveInterval=60' + export SSH_OPTS2='-o ServerAliveCountMax=30' + ssh ${SSH_OPTS1} ${SSH_OPTS2} -o "proxycommand ssh -W %h:%p ${SSH_OPTS1} ${SSH_OPTS2} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} + ``` + For more information, go to [Connecting your nodes over SSH](https://confluence.atlassian.com/adminjiraserver/administering-jira-data-center-on-aws-938846969.html#AdministeringJiraDataCenteronAWS-ConnectingtoyournodesoverSSH). +1. Download the [populate_db.sh](https://github.com/atlassian/dc-app-performance-toolkit/blob/master/app/util/crowd/populate_db.sh) script and make it executable: + + ``` bash + wget https://raw.githubusercontent.com/atlassian/dc-app-performance-toolkit/master/app/util/crowd/populate_db.sh && chmod +x populate_db.sh + ``` +1. Review the following `Variables section` of the script: + + ``` bash + DB_CONFIG="/usr/lib/systemd/system/crowd.service" + CROWD_DB_NAME="crowd" + CROWD_DB_USER="postgres" + CROWD_DB_PASSWORD="Password1!" + ``` +1. Run the script: + + ``` bash + ./populate_db.sh 2>&1 | tee -a populate_db.log + ``` + +{{% note %}} +Do not close or interrupt the session. It will take about an hour to restore SQL database. When SQL restoring is finished, an admin user will have `admin`/`admin` credentials. + +In case of a failure, check the `Variables` section and run the script one more time. +{{% /note %}} + +##### Option 2: Loading the dataset through XML import (~30 minutes) + +We recommend that you only use this method if you are having problems with the [populate_db.sh](https://github.com/atlassian/dc-app-performance-toolkit/blob/master/app/util/crowd/populate_db.sh) script. + +1. In the AWS console, go to **Services** > **EC2** > **Instances**. +1. On the **Description** tab, do the following: + - Copy the _Public IP_ of the Bastion instance. + - Copy the _Private IP_ of the Crowd node instance. +1. Using SSH, connect to the Crowd node via the Bastion instance: + + For Linux or MacOS run following commands in terminal (for Windows use [Git Bash](https://git-scm.com/downloads) terminal): + + ```bash + ssh-add path_to_your_private_key_pem + export BASTION_IP=bastion_instance_public_ip + export NODE_IP=node_private_ip + export SSH_OPTS1='-o ServerAliveInterval=60' + export SSH_OPTS2='-o ServerAliveCountMax=30' + ssh ${SSH_OPTS1} ${SSH_OPTS2} -o "proxycommand ssh -W %h:%p ${SSH_OPTS1} ${SSH_OPTS2} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} + ``` + For more information, go to [Connecting your nodes over SSH](https://confluence.atlassian.com/adminjiraserver/administering-jira-data-center-on-aws-938846969.html#AdministeringJiraDataCenteronAWS-ConnectingtoyournodesoverSSH). +1. Download the db.xml file corresponding to your Crowd version. + + ``` bash + CROWD_VERSION=$(sudo su crowd -c "cat /media/atl/crowd/shared/crowd.version") + sudo su crowd -c "wget https://centaurus-datasets.s3.amazonaws.com/crowd/${CROWD_VERSION}/large/db.xml -O /media/atl/crowd/shared/db.xml" + ``` +1. Log in as a user with the **Crowd System Administrators** [global permission](https://confluence.atlassian.com/adminjiraserver/managing-global-permissions-938847142.html). +1. Go to **![cog icon](/platform/marketplace/images/cog.png) > Restore.** from the menu. +1. Populate the **Restore file path** field with `/media/atl/crowd/shared/db.xml`. +1. Click **Submit** and wait until the import is completed. + +--- + +## <a id="appspecificaction"></a>3. App-specific actions development + +Data Center App Performance Toolkit has its own set of default [JMeter](https://jmeter.apache.org/) test actions for Crowd Data Center. + +**App-specific action** - action (performance test) you have to develop to cover main use cases of your application. Performance test should focus on the common usage of your application and not to cover all possible functionality of your app. For example, application setup screen or other one-time use cases are out of scope of performance testing. + +**JMeter app-specific actions development** + +1. Set up local environment for toolkit using the [README](https://github.com/atlassian/dc-app-performance-toolkit/blob/master/README.md). +1. Check that `crowd.yml` file has correct settings of `application_hostname`, `application_protocol`, `application_port`, `application_postfix`, etc. +1. Navigate to `dc-app-performance-toolkit/app` folder and run from virtualenv(as described in `dc-app-performance-toolkit/README.md`): + + ```python util/jmeter/start_jmeter_ui.py --app crowd``` +1. Open `Crowd` thread group and add new transaction controller. +1. Open newly added transaction controller, and add new HTTP requests (based on your app use cases) into it. +1. Run toolkit locally from `dc-app-performance-toolkit/app` folder with the command +```bzt crowd.yml``` + Make sure that execution is successful. + +--- + +## <a id="executionhost"></a>4. Setting up an execution environment + +For generating performance results suitable for Marketplace approval process use dedicated execution environment. This is a separate AWS EC2 instance to run the toolkit from. Running the toolkit from a dedicated instance but not from a local machine eliminates network fluctuations and guarantees stable CPU and memory performance. + +1. Go to GitHub and create a fork of [dc-app-performance-toolkit](https://github.com/atlassian/dc-app-performance-toolkit). +1. Clone the fork locally, then edit the `crowd.yml` configuration file. Set enterprise-scale Crowd Data Center parameters: + + ``` yaml + application_hostname: test_crowd_instance.atlassian.com # Crowd DC hostname without protocol and port e.g. test-crowd.atlassian.com or localhost + application_protocol: http # http or https + application_port: 80 # 80, 443, 8080, 4990, etc + secure: True # Set False to allow insecure connections, e.g. when using self-signed SSL certificate + application_postfix: # e.g. /crowd in case of url like http://localhost:4990/crowd + admin_login: admin + admin_password: admin + application_name: crowd + application_password: 1111 + load_executor: jmeter + concurrency: 1000 # number of concurrent threads to authenticate random users + test_duration: 45m + ``` + +1. Push your changes to the forked repository. +1. [Launch AWS EC2 instance](https://docs.aws.amazon.com/quickstarts/latest/vmlaunch/step-1-launch-instance.html). + * OS: select from Quick Start `Ubuntu Server 18.04 LTS`. + * Instance type: [`c5.2xlarge`](https://aws.amazon.com/ec2/instance-types/c5/) + * Storage size: `30` GiB +1. Connect to the instance using [SSH](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AccessingInstancesLinux.html) or the [AWS Systems Manager Sessions Manager](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager.html). + + ```bash + ssh -i path_to_pem_file ubuntu@INSTANCE_PUBLIC_IP + ``` + +1. Install [Docker](https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository). Setup manage Docker as a [non-root user](https://docs.docker.com/engine/install/linux-postinstall). +1. Clone forked repository. + + +You'll need to run the toolkit for each [test scenario](#testscenario) in the next section. + +--- + +## <a id="testscenario"></a>5. Running the test scenarios from execution environment against enterprise-scale Crowd Data Center + +Using the Data Center App Performance Toolkit for [Performance and scale testing your Data Center app](/platform/marketplace/developing-apps-for-atlassian-data-center-products/) involves two test scenarios: + +- [Performance regression](#testscenario1) +- [Scalability testing](#testscenario2) + +Each scenario will involve multiple test runs. The following subsections explain both in greater detail. + +#### <a id="testscenario1"></a> Scenario 1: Performance regression + +This scenario helps to identify basic performance issues without a need to spin up a multi-node Crowd DC. Make sure the app does not have any performance impact when it is not exercised. + +##### <a id="regressionrun1"></a> Run 1 (~50 min) + +To receive performance baseline results **without** an app installed and **without** app-specific actions (use code from `master` branch): + +1. Use SSH to connect to execution environment. +1. Run toolkit with docker from the execution environment instance: + + ``` bash + cd dc-app-performance-toolkit + docker pull atlassian/dcapt + docker run --shm-size=4g -v "$PWD:/dc-app-performance-toolkit" atlassian/dcapt crowd.yml + ``` + +1. View the following main results of the run in the `dc-app-performance-toolkit/app/results/crowd/YY-MM-DD-hh-mm-ss` folder: + - `results_summary.log`: detailed run summary + - `results.csv`: aggregated .csv file with all actions and timings + - `bzt.log`: logs of the Taurus tool execution + - `jmeter.*`: logs of the JMeter tool execution + +{{% note %}} +Review `results_summary.log` file under artifacts dir location. Make sure that overall status is `OK` before moving to the next steps. For an enterprise-scale environment run, the acceptable success rate for actions is 95% and above. +{{% /note %}} + +##### <a id="regressionrun2"></a> Run 2 + + +**Performance results generation with the app installed (still use master branch):** + +1. Run toolkit with docker from the execution environment instance: + + ``` bash + cd dc-app-performance-toolkit + docker pull atlassian/dcapt + docker run --shm-size=4g -v "$PWD:/dc-app-performance-toolkit" atlassian/dcapt crowd.yml + ``` + +{{% note %}} +Review `results_summary.log` file under artifacts dir location. Make sure that overall status is `OK` before moving to the next steps. For an enterprise-scale environment run, the acceptable success rate for actions is 95% and above. +{{% /note %}} + + +##### Generating a performance regression report + +To generate a performance regression report: + +1. Use SSH to connect to execution environment. +1. Install and activate the `virtualenv` as described in `dc-app-performance-toolkit/README.md` +1. Allow current user (for execution environment default user is `ubuntu`) to access Docker generated reports: + ``` bash + sudo chown -R ubuntu:ubuntu /home/ubuntu/dc-app-performance-toolkit/app/results + ``` +1. Navigate to the `dc-app-performance-toolkit/app/reports_generation` folder. +1. Edit the `performance_profile.yml` file: + - Under `runName: "without app"`, in the `fullPath` key, insert the full path to results directory of [Run 1](#regressionrun1). + - Under `runName: "with app"`, in the `fullPath` key, insert the full path to results directory of [Run 2](#regressionrun2). +1. Run the following command: + ``` bash + python csv_chart_generator.py performance_profile.yml + ``` +1. In the `dc-app-performance-toolkit/app/results/reports/YY-MM-DD-hh-mm-ss` folder, view the `.csv` file (with consolidated scenario results), the `.png` chart file and performance scenario summary report. + +#### Analyzing report + +Use [scp](https://man7.org/linux/man-pages/man1/scp.1.html) command to copy report artifacts from execution env to local drive: + +1. From local machine terminal (Git bash terminal for Windows) run command: + ``` bash + export EXEC_ENV_PUBLIC_IP=execution_environment_ec2_instance_public_ip + scp -r -i path_to_exec_env_pem ubuntu@$EXEC_ENV_PUBLIC_IP:/home/ubuntu/dc-app-performance-toolkit/app/results/reports ./reports + ``` +1. Once completed, in the `./reports` folder you will be able to review the action timings with and without your app to see its impact on the performance of the instance. If you see an impact (>20%) on any action timing, we recommend taking a look into the app implementation to understand the root cause of this delta. + + +#### <a id="testscenario2"></a> Scenario 2: Scalability testing + +The purpose of scalability testing is to reflect the impact on the customer experience when operating across multiple nodes. For this, you have to run scale testing on your app. + +For many apps and extensions to Atlassian products, there should not be a significant performance difference between operating on a single node or across many nodes in Crowd DC deployment. To demonstrate performance impacts of operating your app at scale, we recommend testing your Crowd DC app in a cluster. + + +###### <a id="run3"></a> Run 3 (~50 min) + +To receive scalability benchmark results for one-node Crowd DC **with** app-specific actions: + +1. Apply app-specific code changes to a new branch of forked repo. +1. Use SSH to connect to execution environment. +1. Pull cloned fork repo branch with app-specific actions. +1. Run toolkit with docker from the execution environment instance: + + ``` bash + cd dc-app-performance-toolkit + docker pull atlassian/dcapt + docker run --shm-size=4g -v "$PWD:/dc-app-performance-toolkit" atlassian/dcapt crowd.yml + ``` + +{{% note %}} +Review `results_summary.log` file under artifacts dir location. Make sure that overall status is `OK` before moving to the next steps. For an enterprise-scale environment run, the acceptable success rate for actions is 95% and above. +{{% /note %}} + + +##### <a id="run4"></a> Run 4 (~50 min) +{{% note %}} +Before scaling your DC make sure that AWS vCPU limit is not lower than needed number. +Use [vCPU limits calculator](https://aws.amazon.com/premiumsupport/knowledge-center/ec2-on-demand-instance-vcpu-increase/) to see current limit. +The same article has instructions on how to increase limit if needed. +{{% /note %}} + +To receive scalability benchmark results for two-node Crowd DC **with** app-specific actions: + +1. In the AWS console, go to **CloudFormation** > **Stack details** > **Select your stack**. +1. On the **Update** tab, select **Use current template**, and then click **Next**. +1. Enter `2` in the **Maximum number of cluster nodes** and the **Minimum number of cluster nodes** fields. +1. Click **Next** > **Next** > **Update stack** and wait until stack is updated. +1. Edit **run parameters** for 2 nodes run. To do it, left uncommented only 2 nodes scenario parameters in `crowd.yml` file. + ``` + # 1 node scenario parameters + # ramp-up: 20s # time to spin all concurrent threads + # total_actions_per_hour: 180000 # number of total JMeter actions per hour + + # 2 nodes scenario parameters + ramp-up: 10s # time to spin all concurrent threads + total_actions_per_hour: 360000 # number of total JMeter actions per hour + + # 4 nodes scenario parameters + # ramp-up: 5s # time to spin all concurrent threads + # total_actions_per_hour: 720000 # number of total JMeter actions per hour + ``` +1. Run toolkit with docker from the execution environment instance: + + ``` bash + cd dc-app-performance-toolkit + docker pull atlassian/dcapt + docker run --shm-size=4g -v "$PWD:/dc-app-performance-toolkit" atlassian/dcapt crowd.yml + ``` + +{{% note %}} +Review `results_summary.log` file under artifacts dir location. Make sure that overall status is `OK` before moving to the next steps. For an enterprise-scale environment run, the acceptable success rate for actions is 95% and above. +{{% /note %}} + + +##### <a id="run5"></a> Run 5 (~50 min) +{{% note %}} +Before scaling your DC make sure that AWS vCPU limit is not lower than needed number. +Use [vCPU limits calculator](https://aws.amazon.com/premiumsupport/knowledge-center/ec2-on-demand-instance-vcpu-increase/) to see current limit. +The same article has instructions on how to increase limit if needed. +{{% /note %}} + +To receive scalability benchmark results for four-node Crowd DC with app-specific actions: + +1. Scale your Crowd Data Center deployment to 4 nodes as described in [Run 4](#run4). +1. Edit **run parameters** for 4 nodes run. To do it, left uncommented only 4 nodes scenario parameters `crowd.yml` file. + ``` + # 1 node scenario parameters + # ramp-up: 20s # time to spin all concurrent threads + # total_actions_per_hour: 180000 # number of total JMeter actions per hour + + # 2 nodes scenario parameters + # ramp-up: 10s # time to spin all concurrent threads + # total_actions_per_hour: 360000 # number of total JMeter actions per hour + + # 4 nodes scenario parameters + ramp-up: 5s # time to spin all concurrent threads + total_actions_per_hour: 720000 # number of total JMeter actions per hour + ``` + +1. Run toolkit with docker from the execution environment instance: + + ``` bash + cd dc-app-performance-toolkit + docker pull atlassian/dcapt + docker run --shm-size=4g -v "$PWD:/dc-app-performance-toolkit" atlassian/dcapt crowd.yml + ``` + +{{% note %}} +Review `results_summary.log` file under artifacts dir location. Make sure that overall status is `OK` before moving to the next steps. For an enterprise-scale environment run, the acceptable success rate for actions is 95% and above. +{{% /note %}} + + +#### Generating a report for scalability scenario + +To generate a scalability report: + +1. Use SSH to connect to execution environment. +1. Allow current user (for execution environment default user is `ubuntu`) to access Docker generated reports: + ``` bash + sudo chown -R ubuntu:ubuntu /home/ubuntu/dc-app-performance-toolkit/app/results + ``` +1. Navigate to the `dc-app-performance-toolkit/app/reports_generation` folder. +1. Edit the `scale_profile.yml` file: + - For `runName: "Node 1"`, in the `fullPath` key, insert the full path to results directory of [Run 3](#run3). + - For `runName: "Node 2"`, in the `fullPath` key, insert the full path to results directory of [Run 4](#run4). + - For `runName: "Node 4"`, in the `fullPath` key, insert the full path to results directory of [Run 5](#run5). +1. Run the following command from the activated `virtualenv` (as described in `dc-app-performance-toolkit/README.md`): + ``` bash + python csv_chart_generator.py scale_profile.yml + ``` +1. In the `dc-app-performance-toolkit/app/results/reports/YY-MM-DD-hh-mm-ss` folder, view the `.csv` file (with consolidated scenario results), the `.png` chart file and summary report. + + +#### Analyzing report + +Use [scp](https://man7.org/linux/man-pages/man1/scp.1.html) command to copy report artifacts from execution env to local drive: + +1. From local terminal (Git bash terminal for Windows) run command: + ``` bash + export EXEC_ENV_PUBLIC_IP=execution_environment_ec2_instance_public_ip + scp -r -i path_to_exec_env_pem ubuntu@$EXEC_ENV_PUBLIC_IP:/home/ubuntu/dc-app-performance-toolkit/app/results/reports ./reports + ``` +1. Once completed, in the `./reports` folder you will be able to review action timings on Crowd Data Center with different numbers of nodes. If you see a significant variation in any action timings between configurations, we recommend taking a look into the app implementation to understand the root cause of this delta. + +{{% warning %}} +After completing all your tests, delete your Crowd Data Center stacks. +{{% /warning %}} + +#### Attaching testing results to DCHELP ticket + +{{% warning %}} +Do not forget to attach performance testing results to your DCHELP ticket. +{{% /warning %}} + +1. Make sure you have two reports folders: one with performance profile and second with scale profile results. + Each folder should have `profile.csv`, `profile.png`, `profile_summary.log` and profile run result archives. +1. Attach two reports folders to your DCHELP ticket. + +## <a id="support"></a> Support +In case of technical questions, issues or problems with DC Apps Performance Toolkit, contact us for support in the [community Slack](http://bit.ly/dcapt_slack) **#data-center-app-performance-toolkit** channel. diff --git a/docs/dc-apps-performance-toolkit-user-guide-jira.md b/docs/dc-apps-performance-toolkit-user-guide-jira.md index 4b945b280..7ca5e7e9a 100644 --- a/docs/dc-apps-performance-toolkit-user-guide-jira.md +++ b/docs/dc-apps-performance-toolkit-user-guide-jira.md @@ -4,7 +4,7 @@ platform: platform product: marketplace category: devguide subcategory: build -date: "2021-04-26" +date: "2021-06-16" --- # Data Center App Performance Toolkit User Guide For Jira @@ -66,7 +66,7 @@ All important parameters are listed and described in this section. For all other | Parameter | Recommended value | | --------- | ----------------- | | Jira Product | Software | -| Version | The Data Center App Performance Toolkit officially supports `8.13.4`, `8.5.12` ([Long Term Support release](https://confluence.atlassian.com/enterprise/atlassian-enterprise-releases-948227420.html)) | +| Version | The Data Center App Performance Toolkit officially supports `8.13.7`, `8.5.15` ([Long Term Support release](https://confluence.atlassian.com/enterprise/atlassian-enterprise-releases-948227420.html)) | **Cluster nodes** @@ -255,7 +255,7 @@ You develop an app that introduces new GET and POST endpoints in Jira Data Cente 1. Extend example of app-specific action in `dc-app-performance-toolkit/app/extension/jira/extension_locust.py`, so that test will call the endpoint with GET request, parse response use these data to call another endpoint with POST request and measure response time. [Code example.](https://github.com/atlassian/dc-app-performance-toolkit/blob/master/app/extension/jira/extension_locust.py) 1. In `dc-app-performance-toolkit/app/jira.yml` set `load_executor: locust` to make `locust` as load executor. -1. Locust uses actions percentage as relative [weights](https://docs.locust.io/en/stable/writing-a-locustfile.html#weight-attribute), so if `some_action: 10` and `standalone_extension: 20` that means that `standalone_extension` will be called twice more. +1. Set desired execution percentage for `standalone_extension`. Default value is `0`, which means that `standalone_extension` action will not be executed. Locust uses actions percentage as relative [weights](https://docs.locust.io/en/stable/writing-a-locustfile.html#weight-attribute), so if `some_action: 10` and `standalone_extension: 20` that means that `standalone_extension` will be called twice more. Set `standalone_extension` weight in accordance with the expected frequency of your app use case compared with other base actions. 1. App-specific tests could be run (if needed) as a specific user. Use `@run_as_specific_user(username='specific_user_username', password='specific_user_password')` decorator for that. 1. Run toolkit with `bzt jira.yml` command to ensure that all Locust actions including `app_specific_action` are successful. @@ -387,7 +387,7 @@ All important parameters are listed and described in this section. For all other | Parameter | Recommended Value | | --------- | ----------------- | | Jira Product | Software | -| Version | The Data Center App Performance Toolkit officially supports `8.13.4`, `8.5.12` ([Long Term Support release](https://confluence.atlassian.com/enterprise/atlassian-enterprise-releases-948227420.html)) | +| Version | The Data Center App Performance Toolkit officially supports `8.13.7`, `8.5.15` ([Long Term Support release](https://confluence.atlassian.com/enterprise/atlassian-enterprise-releases-948227420.html)) | **Cluster nodes** @@ -524,8 +524,9 @@ To populate the database with SQL: ssh-add path_to_your_private_key_pem export BASTION_IP=bastion_instance_public_ip export NODE_IP=node_private_ip - export SSH_OPTS='-o ServerAliveInterval=60 -o ServerAliveCountMax=30' - ssh ${SSH_OPTS} -o "proxycommand ssh -W %h:%p ${SSH_OPTS} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} + export SSH_OPTS1='-o ServerAliveInterval=60' + export SSH_OPTS2='-o ServerAliveCountMax=30' + ssh ${SSH_OPTS1} ${SSH_OPTS2} -o "proxycommand ssh -W %h:%p ${SSH_OPTS1} ${SSH_OPTS2} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} ``` For more information, go to [Connecting your nodes over SSH](https://confluence.atlassian.com/adminjiraserver/administering-jira-data-center-on-aws-938846969.html#AdministeringJiraDataCenteronAWS-ConnectingtoyournodesoverSSH). 1. Download the [populate_db.sh](https://github.com/atlassian/dc-app-performance-toolkit/blob/master/app/util/jira/populate_db.sh) script and make it executable: @@ -574,8 +575,9 @@ We recommend that you only use this method if you are having problems with the [ ssh-add path_to_your_private_key_pem export BASTION_IP=bastion_instance_public_ip export NODE_IP=node_private_ip - export SSH_OPTS='-o ServerAliveInterval=60 -o ServerAliveCountMax=30' - ssh ${SSH_OPTS} -o "proxycommand ssh -W %h:%p ${SSH_OPTS} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} + export SSH_OPTS1='-o ServerAliveInterval=60' + export SSH_OPTS2='-o ServerAliveCountMax=30' + ssh ${SSH_OPTS1} ${SSH_OPTS2} -o "proxycommand ssh -W %h:%p ${SSH_OPTS1} ${SSH_OPTS2} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} ``` For more information, go to [Connecting your nodes over SSH](https://confluence.atlassian.com/adminjiraserver/administering-jira-data-center-on-aws-938846969.html#AdministeringJiraDataCenteronAWS-ConnectingtoyournodesoverSSH). 1. Download the xml_backup.zip file corresponding to your Jira version. @@ -584,7 +586,7 @@ We recommend that you only use this method if you are having problems with the [ JIRA_VERSION=$(sudo su jira -c "cat /media/atl/jira/shared/jira-software.version") sudo su jira -c "wget https://centaurus-datasets.s3.amazonaws.com/jira/${JIRA_VERSION}/large/xml_backup.zip -O /media/atl/jira/shared/import/xml_backup.zip" ``` -1. From a different computer, log in as a user with the **Jira System Administrators** [global permission](https://confluence.atlassian.com/adminjiraserver/managing-global-permissions-938847142.html). +1. Log in as a user with the **Jira System Administrators** [global permission](https://confluence.atlassian.com/adminjiraserver/managing-global-permissions-938847142.html). 1. Go to **![cog icon](/platform/marketplace/images/cog.png) > System > Restore System.** from the menu. 1. Populate the **File name** field with `xml_backup.zip`. 1. Click **Restore** and wait until the import is completed. @@ -605,8 +607,9 @@ Populate DB and restore attachments scripts could be run in parallel in separate ssh-add path_to_your_private_key_pem export BASTION_IP=bastion_instance_public_ip export NODE_IP=node_private_ip - export SSH_OPTS='-o ServerAliveInterval=60 -o ServerAliveCountMax=30' - ssh ${SSH_OPTS} -o "proxycommand ssh -W %h:%p ${SSH_OPTS} ec2-user@$BASTION_IP" ec2-user@${NODE_IP} + export SSH_OPTS1='-o ServerAliveInterval=60' + export SSH_OPTS2='-o ServerAliveCountMax=30' + ssh ${SSH_OPTS1} ${SSH_OPTS2} -o "proxycommand ssh -W %h:%p ${SSH_OPTS1} ${SSH_OPTS2} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} ``` For more information, go to [Connecting your nodes over SSH](https://confluence.atlassian.com/adminjiraserver/administering-jira-data-center-on-aws-938846969.html#AdministeringJiraDataCenteronAWS-ConnectingtoyournodesoverSSH). 1. Download the [upload_attachments.sh](https://github.com/atlassian/dc-app-performance-toolkit/blob/master/app/util/jira/upload_attachments.sh) script and make it executable: @@ -793,7 +796,7 @@ Use [scp](https://man7.org/linux/man-pages/man1/scp.1.html) command to copy repo 1. From local machine terminal (Git bash terminal for Windows) run command: ``` bash export EXEC_ENV_PUBLIC_IP=execution_environment_ec2_instance_public_ip - scp -r -i path_to_exec_env_pem ubuntu@EXEC_ENV_PUBLIC_IP:/home/ubuntu/dc-app-performance-toolkit/app/results/reports ./reports + scp -r -i path_to_exec_env_pem ubuntu@$EXEC_ENV_PUBLIC_IP:/home/ubuntu/dc-app-performance-toolkit/app/results/reports ./reports ``` 1. Once completed, in the `./reports` folder you will be able to review the action timings with and without your app to see its impact on the performance of the instance. If you see an impact (>20%) on any action timing, we recommend taking a look into the app implementation to understand the root cause of this delta. @@ -844,8 +847,9 @@ To receive scalability benchmark results for two-node Jira DC **with** app-speci ssh-add path_to_your_private_key_pem export BASTION_IP=bastion_instance_public_ip export NODE_IP=node_private_ip - export SSH_OPTS='-o ServerAliveInterval=60 -o ServerAliveCountMax=30' - ssh ${SSH_OPTS} -o "proxycommand ssh -W %h:%p ${SSH_OPTS} ec2-user@$BASTION_IP" ec2-user@${NODE_IP} + export SSH_OPTS1='-o ServerAliveInterval=60' + export SSH_OPTS2='-o ServerAliveCountMax=30' + ssh ${SSH_OPTS1} ${SSH_OPTS2} -o "proxycommand ssh -W %h:%p ${SSH_OPTS1} ${SSH_OPTS2} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} ``` 1. Once you're in the second node, download the [index-sync.sh](https://raw.githubusercontent.com/atlassian/dc-app-performance-toolkit/master/app/util/jira/index-sync.sh) file. Then, make it executable and run it: @@ -915,9 +919,9 @@ To generate a scalability report: ``` 1. Navigate to the `dc-app-performance-toolkit/app/reports_generation` folder. 1. Edit the `scale_profile.yml` file: - - For `runName: "Node 1"`, in the `fullPath` key, insert the full path to results directory of [Run 3](#run3). - - For `runName: "Node 2"`, in the `fullPath` key, insert the full path to results directory of [Run 4](#run4). - - For `runName: "Node 4"`, in the `fullPath` key, insert the full path to results directory of [Run 5](#run5). + - For `runName: "1 Node"`, in the `fullPath` key, insert the full path to results directory of [Run 3](#run3). + - For `runName: "2 Nodes"`, in the `fullPath` key, insert the full path to results directory of [Run 4](#run4). + - For `runName: "4 Nodes"`, in the `fullPath` key, insert the full path to results directory of [Run 5](#run5). 1. Run the following command from the activated `virtualenv` (as described in `dc-app-performance-toolkit/README.md`): ``` bash python csv_chart_generator.py scale_profile.yml @@ -932,7 +936,7 @@ Use [scp](https://man7.org/linux/man-pages/man1/scp.1.html) command to copy repo 1. From local terminal (Git bash terminal for Windows) run command: ``` bash export EXEC_ENV_PUBLIC_IP=execution_environment_ec2_instance_public_ip - scp -r -i path_to_exec_env_pem ubuntu@EXEC_ENV_PUBLIC_IP:/home/ubuntu/dc-app-performance-toolkit/app/results/reports ./reports + scp -r -i path_to_exec_env_pem ubuntu@$EXEC_ENV_PUBLIC_IP:/home/ubuntu/dc-app-performance-toolkit/app/results/reports ./reports ``` 1. Once completed, in the `./reports` folder you will be able to review action timings on Jira Data Center with different numbers of nodes. If you see a significant variation in any action timings between configurations, we recommend taking a look into the app implementation to understand the root cause of this delta. diff --git a/docs/dc-apps-performance-toolkit-user-guide-jsm.md b/docs/dc-apps-performance-toolkit-user-guide-jsm.md index 7c6899c66..3f0741aaa 100644 --- a/docs/dc-apps-performance-toolkit-user-guide-jsm.md +++ b/docs/dc-apps-performance-toolkit-user-guide-jsm.md @@ -4,7 +4,7 @@ platform: platform product: marketplace category: devguide subcategory: build -date: "2021-04-26" +date: "2021-06-16" --- # Data Center App Performance Toolkit User Guide For Jira Service Management @@ -66,7 +66,7 @@ All important parameters are listed and described in this section. For all other | Parameter | Recommended value | | --------- | ----------------- | | Jira Product | ServiceManagement | -| Version | The Data Center App Performance Toolkit officially supports `4.13.4`, `4.5.12` ([Long Term Support release](https://confluence.atlassian.com/enterprise/atlassian-enterprise-releases-948227420.html)) | +| Version | The Data Center App Performance Toolkit officially supports `4.13.7`, `4.5.15` ([Long Term Support release](https://confluence.atlassian.com/enterprise/atlassian-enterprise-releases-948227420.html)) | **Cluster nodes** @@ -164,8 +164,9 @@ To populate the database with SQL: ssh-add path_to_your_private_key_pem export BASTION_IP=bastion_instance_public_ip export NODE_IP=node_private_ip - export SSH_OPTS='-o ServerAliveInterval=60 -o ServerAliveCountMax=30' - ssh ${SSH_OPTS} -o "proxycommand ssh -W %h:%p ${SSH_OPTS} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} + export SSH_OPTS1='-o ServerAliveInterval=60' + export SSH_OPTS2='-o ServerAliveCountMax=30' + ssh ${SSH_OPTS1} ${SSH_OPTS2} -o "proxycommand ssh -W %h:%p ${SSH_OPTS1} ${SSH_OPTS2} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} ``` For more information, go to [Connecting your nodes over SSH](https://confluence.atlassian.com/adminjiraserver/administering-jira-data-center-on-aws-938846969.html#AdministeringJiraDataCenteronAWS-ConnectingtoyournodesoverSSH). 1. Download the [populate_db.sh](https://github.com/atlassian/dc-app-performance-toolkit/blob/master/app/util/jira/populate_db.sh) script and make it executable: @@ -211,8 +212,9 @@ We recommend that you only use this method if you are having problems with the [ ssh-add path_to_your_private_key_pem export BASTION_IP=bastion_instance_public_ip export NODE_IP=node_private_ip - export SSH_OPTS='-o ServerAliveInterval=60 -o ServerAliveCountMax=30' - ssh ${SSH_OPTS} -o "proxycommand ssh -W %h:%p ${SSH_OPTS} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} + export SSH_OPTS1='-o ServerAliveInterval=60' + export SSH_OPTS2='-o ServerAliveCountMax=30' + ssh ${SSH_OPTS1} ${SSH_OPTS2} -o "proxycommand ssh -W %h:%p ${SSH_OPTS1} ${SSH_OPTS2} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} ``` For more information, go to [Connecting your nodes over SSH](https://confluence.atlassian.com/adminjiraserver/administering-jira-data-center-on-aws-938846969.html#AdministeringJiraDataCenteronAWS-ConnectingtoyournodesoverSSH). 1. Download the xml_backup.zip file corresponding to your Jira Service Management version. @@ -221,7 +223,7 @@ We recommend that you only use this method if you are having problems with the [ JSM_VERSION=$(sudo su jira -c "cat /media/atl/jira/shared/jira-servicedesk.version") sudo su jira -c "wget https://centaurus-datasets.s3.amazonaws.com/jira/${JSM_VERSION}/small/xml_backup.zip -O /media/atl/jira/shared/import/xml_backup.zip" ``` -1. From a different computer, log in as a user with the **Jira System Administrators** [global permission](https://confluence.atlassian.com/adminjiraserver/managing-global-permissions-938847142.html). +1. Log in as a user with the **Jira System Administrators** [global permission](https://confluence.atlassian.com/adminjiraserver/managing-global-permissions-938847142.html). 1. Go to **![cog icon](/platform/marketplace/images/cog.png) > System > Restore System.** from the menu. 1. Populate the **File name** field with `xml_backup.zip`. 1. Click **Restore** and wait until the import is completed. @@ -236,8 +238,9 @@ We recommend that you only use this method if you are having problems with the [ ssh-add path_to_your_private_key_pem export BASTION_IP=bastion_instance_public_ip export NODE_IP=node_private_ip - export SSH_OPTS='-o ServerAliveInterval=60 -o ServerAliveCountMax=30' - ssh ${SSH_OPTS} -o "proxycommand ssh -W %h:%p ${SSH_OPTS} ec2-user@$BASTION_IP" ec2-user@${NODE_IP} + export SSH_OPTS1='-o ServerAliveInterval=60' + export SSH_OPTS2='-o ServerAliveCountMax=30' + ssh ${SSH_OPTS1} ${SSH_OPTS2} -o "proxycommand ssh -W %h:%p ${SSH_OPTS1} ${SSH_OPTS2} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} ``` For more information, go to [Connecting your nodes over SSH](https://confluence.atlassian.com/adminjiraserver/administering-jira-data-center-on-aws-938846969.html#AdministeringJiraDataCenteronAWS-ConnectingtoyournodesoverSSH). 1. Download the [upload_attachments.sh](https://github.com/atlassian/dc-app-performance-toolkit/blob/master/app/util/jira/upload_attachments.sh) script and make it executable: @@ -386,7 +389,7 @@ You develop an app that introduces new GET and POST endpoints in Jira Service Ma 1. Extend example of app-specific action for customers in `dc-app-performance-toolkit/app/extension/jsm/extension_locust_customers.py`, so that test will call the endpoint with GET request, parse response use these data to call another endpoint with POST request and measure response time. [Code example.](https://github.com/atlassian/dc-app-performance-toolkit/blob/master/app/extension/jsm/extension_locust_customers.py) 1. In `dc-app-performance-toolkit/app/jsm.yml` set `load_executor: locust` to make `locust` as load executor. -1. Locust uses actions percentage as relative [weights](https://docs.locust.io/en/stable/writing-a-locustfile.html#weight-attribute), so if `some_action: 10` and `standalone_extension: 20` that means that `standalone_extension` will be called twice more. +1. Set desired execution percentage for `agent_standalone_extension`/`customer_standalone_extension`. Default value is `0`, which means that `agent_standalone_extension`/`customer_standalone_extension` action will not be executed. Locust uses actions percentage as relative [weights](https://docs.locust.io/en/stable/writing-a-locustfile.html#weight-attribute), so if `some_action: 10` and `standalone_extension: 20` that means that `standalone_extension` will be called twice more. Set `agent_standalone_extension`/`customer_standalone_extension` weight in accordance with the expected frequency of your app use case compared with other base actions. 1. App-specific tests could be run (if needed) as a specific user. Use `@run_as_specific_user(username='specific_user_username', password='specific_user_password')` decorator for that. 1. Run toolkit with `bzt jsm.yml` command to ensure that all Locust actions including `app_specific_action` are successful. @@ -540,7 +543,7 @@ All important parameters are listed and described in this section. For all other | Parameter | Recommended Value | | --------- | ----------------- | | Jira Product | ServiceManagement | -| Version | The Data Center App Performance Toolkit officially supports `4.13.4`, `4.5.12` ([Long Term Support release](https://confluence.atlassian.com/enterprise/atlassian-enterprise-releases-948227420.html)) | +| Version | The Data Center App Performance Toolkit officially supports `4.13.7`, `4.5.15` ([Long Term Support release](https://confluence.atlassian.com/enterprise/atlassian-enterprise-releases-948227420.html)) | **Cluster nodes** @@ -671,8 +674,9 @@ To populate the database with SQL: ssh-add path_to_your_private_key_pem export BASTION_IP=bastion_instance_public_ip export NODE_IP=node_private_ip - export SSH_OPTS='-o ServerAliveInterval=60 -o ServerAliveCountMax=30' - ssh ${SSH_OPTS} -o "proxycommand ssh -W %h:%p ${SSH_OPTS} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} + export SSH_OPTS1='-o ServerAliveInterval=60' + export SSH_OPTS2='-o ServerAliveCountMax=30' + ssh ${SSH_OPTS1} ${SSH_OPTS2} -o "proxycommand ssh -W %h:%p ${SSH_OPTS1} ${SSH_OPTS2} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} ``` For more information, go to [Connecting your nodes over SSH](https://confluence.atlassian.com/adminjiraserver/administering-jira-data-center-on-aws-938846969.html#AdministeringJiraDataCenteronAWS-ConnectingtoyournodesoverSSH). 1. Download the [populate_db.sh](https://github.com/atlassian/dc-app-performance-toolkit/blob/master/app/util/jira/populate_db.sh) script and make it executable: @@ -720,8 +724,9 @@ We recommend that you only use this method if you are having problems with the [ ssh-add path_to_your_private_key_pem export BASTION_IP=bastion_instance_public_ip export NODE_IP=node_private_ip - export SSH_OPTS='-o ServerAliveInterval=60 -o ServerAliveCountMax=30' - ssh ${SSH_OPTS} -o "proxycommand ssh -W %h:%p ${SSH_OPTS} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} + export SSH_OPTS1='-o ServerAliveInterval=60' + export SSH_OPTS2='-o ServerAliveCountMax=30' + ssh ${SSH_OPTS1} ${SSH_OPTS2} -o "proxycommand ssh -W %h:%p ${SSH_OPTS1} ${SSH_OPTS2} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} ``` For more information, go to [Connecting your nodes over SSH](https://confluence.atlassian.com/adminjiraserver/administering-jira-data-center-on-aws-938846969.html#AdministeringJiraDataCenteronAWS-ConnectingtoyournodesoverSSH). 1. Download the xml_backup.zip file corresponding to your Jira Service Management version. @@ -730,7 +735,7 @@ We recommend that you only use this method if you are having problems with the [ JSM_VERSION=$(sudo su jira -c "cat /media/atl/jira/shared/jira-servicedesk.version") sudo su jira -c "wget https://centaurus-datasets.s3.amazonaws.com/jira/${JSM_VERSION}/large/xml_backup.zip -O /media/atl/jira/shared/import/xml_backup.zip" ``` -1. From a different computer, log in as a user with the **Jira System Administrators** [global permission](https://confluence.atlassian.com/adminjiraserver/managing-global-permissions-938847142.html). +1. Log in as a user with the **Jira System Administrators** [global permission](https://confluence.atlassian.com/adminjiraserver/managing-global-permissions-938847142.html). 1. Go to **![cog icon](/platform/marketplace/images/cog.png) > System > Restore System.** from the menu. 1. Populate the **File name** field with `xml_backup.zip`. 1. Click **Restore** and wait until the import is completed. @@ -751,8 +756,9 @@ Populate DB and restore attachments scripts could be run in parallel in separate ssh-add path_to_your_private_key_pem export BASTION_IP=bastion_instance_public_ip export NODE_IP=node_private_ip - export SSH_OPTS='-o ServerAliveInterval=60 -o ServerAliveCountMax=30' - ssh ${SSH_OPTS} -o "proxycommand ssh -W %h:%p ${SSH_OPTS} ec2-user@$BASTION_IP" ec2-user@${NODE_IP} + export SSH_OPTS1='-o ServerAliveInterval=60' + export SSH_OPTS2='-o ServerAliveCountMax=30' + ssh ${SSH_OPTS1} ${SSH_OPTS2} -o "proxycommand ssh -W %h:%p ${SSH_OPTS1} ${SSH_OPTS2} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} ``` For more information, go to [Connecting your nodes over SSH](https://confluence.atlassian.com/adminjiraserver/administering-jira-data-center-on-aws-938846969.html#AdministeringJiraDataCenteronAWS-ConnectingtoyournodesoverSSH). 1. Download the [upload_attachments.sh](https://github.com/atlassian/dc-app-performance-toolkit/blob/master/app/util/jira/upload_attachments.sh) script and make it executable: @@ -939,7 +945,7 @@ Use [scp](https://man7.org/linux/man-pages/man1/scp.1.html) command to copy repo 1. From local machine terminal (Git bash terminal for Windows) run command: ``` bash export EXEC_ENV_PUBLIC_IP=execution_environment_ec2_instance_public_ip - scp -r -i path_to_exec_env_pem ubuntu@EXEC_ENV_PUBLIC_IP:/home/ubuntu/dc-app-performance-toolkit/app/results/reports ./reports + scp -r -i path_to_exec_env_pem ubuntu@$EXEC_ENV_PUBLIC_IP:/home/ubuntu/dc-app-performance-toolkit/app/results/reports ./reports ``` 1. Once completed, in the `./reports` folder you will be able to review the action timings with and without your app to see its impact on the performance of the instance. If you see an impact (>20%) on any action timing, we recommend taking a look into the app implementation to understand the root cause of this delta. @@ -989,8 +995,9 @@ To receive scalability benchmark results for two-node Jira Service Management DC ssh-add path_to_your_private_key_pem export BASTION_IP=bastion_instance_public_ip export NODE_IP=node_private_ip - export SSH_OPTS='-o ServerAliveInterval=60 -o ServerAliveCountMax=30' - ssh ${SSH_OPTS} -o "proxycommand ssh -W %h:%p ${SSH_OPTS} ec2-user@$BASTION_IP" ec2-user@${NODE_IP} + export SSH_OPTS1='-o ServerAliveInterval=60' + export SSH_OPTS2='-o ServerAliveCountMax=30' + ssh ${SSH_OPTS1} ${SSH_OPTS2} -o "proxycommand ssh -W %h:%p ${SSH_OPTS1} ${SSH_OPTS2} ec2-user@${BASTION_IP}" ec2-user@${NODE_IP} ``` 1. Once you're in the second node, download the [index-sync.sh](https://raw.githubusercontent.com/atlassian/dc-app-performance-toolkit/master/app/util/jira/index-sync.sh) file. Then, make it executable and run it: @@ -1060,9 +1067,9 @@ To generate a scalability report: ``` 1. Navigate to the `dc-app-performance-toolkit/app/reports_generation` folder. 1. Edit the `scale_profile.yml` file: - - For `runName: "Node 1"`, in the `fullPath` key, insert the full path to results directory of [Run 3](#run3). - - For `runName: "Node 2"`, in the `fullPath` key, insert the full path to results directory of [Run 4](#run4). - - For `runName: "Node 4"`, in the `fullPath` key, insert the full path to results directory of [Run 5](#run5). + - For `runName: "1 Node"`, in the `fullPath` key, insert the full path to results directory of [Run 3](#run3). + - For `runName: "2 Nodes"`, in the `fullPath` key, insert the full path to results directory of [Run 4](#run4). + - For `runName: "4 Nodes"`, in the `fullPath` key, insert the full path to results directory of [Run 5](#run5). 1. Run the following command from the activated `virtualenv` (as described in `dc-app-performance-toolkit/README.md`): ``` bash python csv_chart_generator.py scale_profile.yml @@ -1077,7 +1084,7 @@ Use [scp](https://man7.org/linux/man-pages/man1/scp.1.html) command to copy repo 1. From local terminal (Git bash terminal for Windows) run command: ``` bash export EXEC_ENV_PUBLIC_IP=execution_environment_ec2_instance_public_ip - scp -r -i path_to_exec_env_pem ubuntu@EXEC_ENV_PUBLIC_IP:/home/ubuntu/dc-app-performance-toolkit/app/results/reports ./reports + scp -r -i path_to_exec_env_pem ubuntu@$EXEC_ENV_PUBLIC_IP:/home/ubuntu/dc-app-performance-toolkit/app/results/reports ./reports ``` 1. Once completed, in the `./reports` folder, you will be able to review action timings on Jira Service Management Data Center with different numbers of nodes. If you see a significant variation in any action timings between configurations, we recommend taking a look into the app implementation to understand the root cause of this delta. diff --git a/requirements.txt b/requirements.txt index 8f93de340..e191655b2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ -matplotlib==3.4.1 +matplotlib==3.4.2 pandas==1.2.4 -importlib-metadata==4.0.1 +importlib-metadata==4.5.0 bzt==1.15.3 locust==1.4.4 filelock==3.0.12 \ No newline at end of file