Forcibly closed connection causing test to fail

Hi,
I have a test script that does a few page changes using client javascript calls but it constantly crashes with: “An existing connection was forcibly closed”

I cannot seem to understand why k6 breaks, maybe you have some ideas?
It seems like K6 is perhaps timing out or interpreting some failure to load woffs as a failure to load the page?

A second problem is that once it closes it context there is no way for me to measure that and take action. Preferably I want to keep the same context as to not download to much data while testing.

Any ideas?

The data and log is from a short moc run over only 60s in order to make replicating easier.

The complete log is (URL blanked out):

  execution: local
     script: scripts\moctest.js
     output: -

  scenarios: (100.00%) 1 scenario, 2 max VUs, 1m50s max duration (incl. graceful stop):
           * default: Up to 2 looping VUs for 1m20s over 3 stages (gracefulRampDown: 30s, gracefulStop: 30s)

INFO[0002] :: Running setup                              source=console
INFO[0002] [1]:: requests: 5                             source=console
INFO[0002] [1]request time: 9000                         source=console
INFO[0002] [1]:: sleeping for 8.996s                     source=console
INFO[0011] [1]:: create context                          source=console
INFO[0012] [2]:: requests: 2                             source=console
INFO[0013] [2]request time: 58000                        source=console
INFO[0013] [2]:: sleeping for 57.223s                    source=console
INFO[0013] :: goto: https://MY.DOMAIN.com/pnt_fix_prod/Default.aspx?login=1&pageid=0  source=console
INFO[0015] [1]=====================> 1                   source=console
INFO[0016] [1]request time: 27000                        source=console
INFO[0016] [1]:: sleeping for 13.539s                    source=console
WARN[0017] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://goo.gl/7K7WLu  browser_source=other line_number=233 source=browser url="https://MY.DOMAIN.com/pnt_fix_prod/include/amd/Highcharts%209.0.1.0/modules/sonification.js"
INFO[0029] [1]:: navigate to subl2g0tci1tglh9jo6j29      source=console
INFO[0029] :: goto pageid: subl2g0tci1tglh9jo6j29        source=console
WARN[0031] url:https://MY.DOMAIN.com/pnt_fix_prod/themes/X/fonts/fontawesome/webfonts/fa-regular-400.woff2 method:GET err:error fetching response body: No data found for resource with given identifier (-32000)  category="Response:bodySize:fetchBody" elapsed="0 ms" goroutine=65
WARN[0031] url:https://MY.DOMAIN.com/pnt_fix_prod/themes/X/fonts/fontawesome/webfonts/fa-solid-900.woff2 method:GET err:error fetching response body: No data found for resource with given identifier (-32000)  category="Response:bodySize:fetchBody" elapsed="0 ms" goroutine=65
INFO[0031] [1]=====================> 2                   source=console
INFO[0031] [1]request time: 35000                        source=console
INFO[0031] [1]:: sleeping for 5.888s                     source=console
INFO[0037] [1]:: navigate to searchpage                  source=console
INFO[0037] :: goto pageid: searchpage                    source=console
WARN[0039] url:https://MY.DOMAIN.com/pnt_fix_prod/themes/X/fonts/fontawesome/webfonts/fa-regular-400.woff2 method:GET err:error fetching response body: No data found for resource with given identifier (-32000)  category="Response:bodySize:fetchBody" elapsed="0 ms" goroutine=65
WARN[0039] url:https://MY.DOMAIN.com/pnt_fix_prod/themes/X/fonts/fontawesome/webfonts/fa-solid-900.woff2 method:GET err:error fetching response body: No data found for resource with given identifier (-32000)  category="Response:bodySize:fetchBody" elapsed="0 ms" goroutine=65
INFO[0039] [1]=====================> 3                   source=console
INFO[0039] [1]request time: 46000                        source=console
INFO[0039] [1]:: sleeping for 8.915s                     source=console
ERRO[0041] err:read tcp 127.0.0.1:64886->127.0.0.1:64885: wsarecv: An existing connection was forcibly closed by the remote host.  category="Connection:handleIOError" elapsed="0 ms" goroutine=45
INFO[0048] [1]:: navigate to subl2g0tci1tglh9jo6j29      source=console
INFO[0048] :: goto pageid: subl2g0tci1tglh9jo6j29        source=console
ERRO[0049] wsURL:"ws://127.0.0.1:64885/devtools/browser/eeb495d7-382e-444b-b125-0bf70928cc15" sid:41EACE412790FCD6DC32C1F7DA32EBD7 err:context canceled  category="Connection:send:<-c.ctx.Done()" elapsed="7996 ms" goroutine=34
ERRO[0049] [1]:: ERROR :: error calling evaluate: frame cannot evaluate: cannot call function on expression ("pid => _W.GoToPageId(pid)\n//# sourceURL=__xk6_browser_evaluation_script__\n") in execution context (7) in frame (1F1969461A362C929196BA1CD6A65D06) with session (41EACE412790FCD6DC32C1F7DA32EBD7): context canceled  source=console
INFO[0049] [1]:: closing page                            source=console
INFO[0049] [1]request time: 60000                        source=console
INFO[0049] [1]:: sleeping for 12.961s                    source=console
INFO[0062] [1]:: create new page                         source=console
ERRO[0062] [1]:: ERROR :: newPageInContext: missing browser context: 502999377E10F37D948649892A8E6C90  source=console
INFO[0062] [1]:: closing page                            source=console
INFO[0062] [1]request time: 9000                         source=console
INFO[0062] [1]:: create new page                         source=console
ERRO[0062] [1]:: ERROR :: newPageInContext: missing browser context: 502999377E10F37D948649892A8E6C90  source=console
INFO[0062] [1]:: closing page                            source=console
ERRO[0062] wsURL:"ws://127.0.0.1:64885/devtools/browser/eeb495d7-382e-444b-b125-0bf70928cc15" sid: err:context canceled  category="Connection:send:<-ctx.Done()" elapsed="13032 ms" goroutine=34
ERRO[0062] cannot dispose browser context: unable to dispose browser context *target.DisposeBrowserContextParams: context canceled
        at reflect.methodValueCall (native)
        at file:///C:/Program%20Files/k6/scripts/moctest.js:128:6(378)
        at native  executor=ramping-vus scenario=default source=stacktrace
INFO[0062] [1]:: requests: 5                             source=console
INFO[0062] [1]request time: 9000                         source=console
INFO[0062] [1]:: sleeping for 8.988s                     source=console
INFO[0071] [2]:: create context                          source=console
INFO[0071] :: goto: https://MY.DOMAIN.com/pnt_fix_prod/Default.aspx?login=1&pageid=0  source=console
INFO[0071] [1]:: create context                          source=console
INFO[0073] [2]=====================> 1                   source=console
INFO[0074] [2]request time: 62000                        source=console
INFO[0073] :: goto: https://MY.DOMAIN.com/pnt_fix_prod/Default.aspx?login=1&pageid=0  source=console
WARN[0074] url:https://MY.DOMAIN.com/pnt_fix_prod/include/amd/Highcharts%209.0.1.0/highcharts.js method:GET err:error fetching response body: context canceled  category="Response:bodySize:fetchBody" elapsed="0 ms" goroutine=1754

And the complete moc script:

import { SharedArray } from 'k6/data';
import { sleep } from "k6";
import launcher from "k6/x/browser";
import { vu, test } from "k6/execution";

const baseUrl = 'https://MY.DOMAIN.com/pnt_fix_prod/Default.aspx'
const startPages = ['0']
const pages = ['0','searchpage','c1','subl2g0tci1tglh9jo6j29']
const jitter = 10 // 1800 // seconds
const cooldown = '10s'
const duration = 60 // 3600 // seconds
const headless = true
const sod_start = 13*24*60*60*1000+10*60*60*1000 + 50000 // 10:00
const t0 = sod_start
const t1 = t0 + duration*1000 // +1h
const dryrun = false

const vu_reqs = new SharedArray('reqs', function () {
  return [
    [{"t":9000,"session":"t0_159","islast":false},{"t":27000,"session":"t0_159","islast":false},{"t":35000,"session":"t0_159","islast":false},{"t":46000,"session":"t0_159","islast":false},{"t":60000,"session":"t0_159","islast":false}],
    [{"t":58000,"session":"t0_25","islast":false},{"t":62000,"session":"t0_25","islast":false}]
  ]
})

export let options = {
  stages: [
      { target: vu_reqs.length, duration: dryrun ? 1 : jitter + "s" },
      { target: vu_reqs.length, duration: dryrun ? 1 : duration + "s" },
      { target: 0, duration: dryrun ? 1 : cooldown }
  ],
  thresholds: {
      "http_req_duration": ["p(95)<500"],
      "http_req_duration{staticAsset:yes}": ["p(99)<250"],
  },
}

function start(config = {headless: true}) {
  const browser = launcher.launch('chromium', config)
  const context = browser.newContext()
  const page = context.newPage()
  return {browser, context, page}
}
function openPage(ctx) {
  ctx.page = ctx.context.newPage()
  return ctx
}
function setUrl(ctx, url) {
  console.log(":: goto: " + url)
  ctx.page.goto(url, { waitUntil: 'load' })
}
function gotoPageId(ctx, pageId) {
  console.log(":: goto pageid: " + pageId)
  sleep(1) // Just for more safety
  ctx.page.evaluate((pid) => _W.GoToPageId(pid), pageId)
  sleep(1) // Just for more safety
  ctx.page.waitForLoadState('load')
}

let trueStartTime = Date.now()

export function setup() {
  console.log(":: Running setup")
  if(dryrun) console.warn("THIS IS A DRY RUN")
  trueStartTime = Date.now()
}

export default function(data) {
  if(dryrun) return

  let startTime = Date.now()
  let vuRampup = jitter - ((startTime - trueStartTime) / 1000)
  let counter = 0
  let ctx = null

  const reqs = vu_reqs[vu.idInTest - 1]
  console.log("[" + vu.idInTest + "]" + ':: requests: ' + reqs.length)
  const reqsCount = reqs.length
  let isClosed = true
  for(let i = 0; i < reqsCount; i++ ) {
    const req = reqs[i]
    console.log("[" + vu.idInTest + "]" + 'request time: ' + req.t)
    let now = Date.now()
    let t = now - startTime

    if((t / 1000) >= vuRampup + duration) {
      test.abort("[" + vu.idInTest + "]" + "==> TIME IS UP 1!")
      break;
    }

    if (req.t > t) {
      const sleepTime = req.t - t
      if(((t + sleepTime) / 1000) >= vuRampup + duration) {
        console.log("[" + vu.idInTest + "]" + "==> Test duration is up! Exiting.", t, sleepTime, vuRampup, duration)
        break;
      }
      console.log("[" + vu.idInTest + "]" + ":: sleeping for " + ((req.t - t) / 1000) + "s")
      sleep(sleepTime / 1000)
    }
    try {
      if (!ctx) {
        console.log("[" + vu.idInTest + "]" + ":: create context")
        ctx = start({headless})
        setUrl(ctx, baseUrl + '?login=1&pageid=' + startPages[((Math.random() * startPages.length) | 0)]) // Start at start page
        isClosed = false
      } else {
        if (ctx && isClosed) {
          console.log("[" + vu.idInTest + "]" + ":: create new page")
          ctx = openPage(ctx)
          setUrl(ctx, baseUrl + '?login=1&pageid=' + startPages[((Math.random() * startPages.length) | 0)]) // Start at start page
          isClosed = false
        } else {
          let pageId = pages[(Math.random() * pages.length) | 0]
          console.log("[" + vu.idInTest + "]" + ":: navigate to " + pageId)
          gotoPageId(ctx, pageId) // Go to random page
          isClosed = false
        }
      }
      console.log("[" + vu.idInTest + "]" + "=====================> " + (++counter))
    } catch (err) {
      console.error("[" + vu.idInTest + "]" + ":: ERROR :: " + err)
      console.log("[" + vu.idInTest + "]" + ":: closing page")
      ctx.page.close()
      isClosed = true
      if(i === reqsCount - 1) i = -1;
      continue;
    }
    if(req.islast) {
      console.log("[" + vu.idInTest + "]" + ":: is last in session, closing page")
      if(ctx) {
        ctx.page.close()
        isClosed = true
      }
      break;
    }
    if(i === reqsCount - 1) i = -1;
  
  }

  if(ctx) {
    if(!ctx.page.isClosed) {
      ctx.page.close()
    }
    if(ctx.browser) {
      ctx.browser.close()
      ctx.browser = null
    }
  }
  sleep(jitter + duration - ((Date.now() - trueStartTime)  / 1000))
  if((jitter + duration - ((Date.now() - trueStartTime) / 1000)) <= 0) {
    test.abort("[" + vu.idInTest + "]" + "==> TIME IS UP 2!")
  }
}

Hi @Goodgive,

It seems like the browser context error starts happening after getting the following error:

The first thing that comes to mind is that the remote server somehow refuses connections.

There is another error related to _W.GoToPageId method that says the function does not exist on the page. It’s probably because the connection to the browser is gone. Then again, maybe you could try waiting for the function first using waitForFunction. This probably won’t solve the problem as I believe the error is happening because of the remote host somehow.

Please let me know how it goes.

I did as you asked and replaced:
ctx.page.evaluate((pid) => _W.GoToPageId(pid), pageId)
with
ctx.page.waitForFunction((pid) => _W.GoToPageId(pid), pageId)

But it seems that wait for function does not pass the parameter along as it should as I get this error now.

ERRO[0029] Failed to load resource: the server responded with a status of 500 (Internal Server Error)  browser_source=network line_number=0 source=browser stacktrace="<nil>" url="https://MY.DOMAIN.com/pnt_fix_prod/Default.aspx?pageid=undefined&wb_sessionid=d698acbd-7ef3-4a85-bc87-2ba2f30af34a&wb_nonce=f4f67da9-90ff-4c57-b305-055a4cbc3bcf&__timestamp=1654091690615"

where pageid=undefined causes server error.

Am I using it wrong or is there a bug there?
//J

1 Like

Hello again,
I notice that nomatter the timing of my requests it always dies 30s after the first request.
So someone is timing out.
Of course I have tried calling the same addresses manually in Chrome and there is no error or timeout there that I can see. Also the other navigations go through and pages do change and load in the test, until the connection dies.

Hmm, that’s interesting because our default timeout is 30 seconds! Could you try increasing the browser context navigation and default timeouts using setDefaultNavigationTimeout and setDefaultTimeout using the browser context object?

I changed the start function to:

function start(config = {headless: true}) {
  const browser = launcher.launch('chromium', config)
  const context = browser.newContext()
  context.setDefaultNavigationTimeout(60)
  context.setDefaultTimeout(60)
  const page = context.newPage()
  return {browser, context, page}
}

But it still timesout after 30.

I also discussed this with my coworker, who suggested that waitForLoadState('load') could be timing out. If you’re expecting navigation after the evaluate() call, waitForSelector() would probably work better. And lastly, we don’t recommend using sleep calls in the scripts (as sleeping might cause synchronization problems in xk6-browser and the Chrome browser internals).

Well I expect navigation to happen after all the calls. First call is setting the URL and the rest make a JS call that changes the page. And with headless = false, I see the page load as well.
Also it seems that the timeout the happens in the first call which is using goto with waitUntil:

function setUrl(ctx, url) {
  console.log(":: goto: " + url)
  ctx.page.goto(url, { waitUntil: 'load' })
}

What should I use if I need to wait some seconds before I navigate in order to simulate a flow of requests previously recorded?

Hi,
The same timeout happens even with just 1 request, by changing the request array to:

const vu_reqs = new SharedArray('reqs', function () {
  return [
    [{"t":2000,"session":"t0_159","islast":false},{"t":40000,"session":"t0_159","islast":false}]
  ]
})

In other words there is only one page.goto(url, { waitUntil: 'load' }) call and no other actions before the crash.

After going to a page, you might try to wait for an element using waitForSelector to wait until it’s loaded by checking whether a necessary element is on the page.

We don’t currently offer a way to wait :frowning: The philosophy we follow is similar to what is explained in this article. What happens if you don’t use sleep at all?

I will test not sleeping, but this would kind of ruin the usecase since I cannot control the amount of request per time unit then.

I simplified the code more.
Logs are the same.
Basically it seems as if the VU is timing out?

INFO[0000] :: Running setup                              source=console
INFO[0002] :: goto: https://MY.DOMAIN.com/pnt_fix_prod/Default.aspx?login=1&pageid=0  source=console
WARN[0004] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://goo.gl/7K7WLu  browser_source=other line_number=233 source=browser url="https://MY.DOMAIN.com/pnt_fix_prod/include/amd/Highcharts%209.0.1.0/modules/sonification.js"
ERRO[0030] err:read tcp 127.0.0.1:64362->127.0.0.1:64361: wsarecv: An existing connection was forcibly closed by the remote host.  category="Connection:handleIOError" elapsed="0 ms" goroutine=49
import { SharedArray } from 'k6/data';
import { sleep } from "k6";
import launcher from "k6/x/browser";
import { vu, test } from "k6/execution";

const baseUrl = 'https://MY.DOMAIN.com/pnt_fix_prod/Default.aspx'
const startPages = ['0']
const pages = ['0','searchpage','c1','subl2g0tci1tglh9jo6j29']
const jitter = 0 // 1800 // seconds
const cooldown = '10s'
const duration = 60 // 3600 // seconds
const headless = true
const sod_start = 13*24*60*60*1000+10*60*60*1000 + 50000 // 10:00
const t0 = sod_start
const t1 = t0 + duration*1000 // +1h
const dryrun = false

const vu_reqs = new SharedArray('reqs', function () {
  return [
    [{"t":2000,"session":"t0_159","islast":false},{"t":40000,"session":"t0_159","islast":false}]
  ]
})

export let options = {
  stages: [
      { target: vu_reqs.length, duration: dryrun ? 1 : duration + "s" }
  ],
  thresholds: {
      "http_req_duration": ["p(95)<500"],
      "http_req_duration{staticAsset:yes}": ["p(99)<250"],
  },
}

function start(config = {headless: true}) {
  const browser = launcher.launch('chromium', config)
  const context = browser.newContext()
  context.setDefaultNavigationTimeout(60)
  context.setDefaultTimeout(60)
  const page = context.newPage()
  return {browser, context, page}
}

function setUrl(ctx, url) {
  console.log(":: goto: " + url)
  ctx.page.goto(url, { waitUntil: 'load' })
}

let trueStartTime = Date.now()

export function setup() {
  console.log(":: Running setup")
  if(dryrun) console.warn("THIS IS A DRY RUN")
  trueStartTime = Date.now()
}

export default function(data) {
  let ctx = start({headless})
  setUrl(ctx, baseUrl + '?login=1&pageid=' + startPages[((Math.random() * startPages.length) | 0)]) // Start at start page

  sleep(40)

  if(ctx) {
    if(!ctx.page.isClosed) {
      ctx.page.close()
    }
    if(ctx.browser) {
      ctx.browser.close()
      ctx.browser = null
    }
  }
}

Hmm, there is another error there (The AudioContext was not allowed to start). You might try to grant audio permission to the browser context. Could you take a look at this issue? Here’s an example. You need to use xk6-browser from our main branch since we have not released the fix yet.

It might help if you can provide us with a page where we can replicate the problematic behavior.

If I just remove all waits and made it start on a different page where the audiocontext is not used the function looks like this:

export default function(data) {
  let ctx = start({headless})
  ctx.page.goto(baseUrl + '?login=1&pageid=' + startPages[((Math.random() * startPages.length) | 0)], { waitUntil: 'load' }) // Start at start page

  ctx.page.close()
  ctx.browser.close()
}

But it seem to fail to close it nicely:

INFO[0000] :: Running setup                              source=console
WARN[0002] url:https://MY.DOMAIN.com/pnt_fix_prod/themes/X/fonts/fonts.css?v=6.0.8175.25369 method:GET err:error fetching response body: context canceled  category="Response:bodySize:fetchBody" elapsed="0 ms" goroutine=57
WARN[0004] url:https://MY.DOMAIN.com/pnt_fix_prod/themes/X/fonts/fonts.css?v=6.0.8175.25369 method:GET err:error fetching response body: context canceled  category="Response:bodySize:fetchBody" elapsed="0 ms" goroutine=500
ERRO[0004] err:websocket: close 1006 (abnormal closure): unexpected EOF  category="Connection:handleIOError" elapsed="0 ms" goroutine=390

And why are the font downloads failing? Do you have a max document size?

Also, the sleep() command is used in the K6 examples, and it does seem to work and wait fine.
Maybe you have a 30s timeout on the VUs?

Hi,
Simple repo:

export default function(data) {
  const browser = launcher.launch('chromium', {headless: true})
  const context = browser.newContext({
  })
  context.setDefaultNavigationTimeout(60)
  context.setDefaultTimeout(60)
  const page = context.newPage()
  page.goto('https://www.google.com/', { waitUntil: 'load' }) // Start at start page
  sleep(40)
  page.close()
  browser.close()
}

Both errors are there. The timeout after 30s…

INFO[0000] :: Running setup                              source=console
ERRO[0030] err:read tcp 127.0.0.1:51033->127.0.0.1:51032: wsarecv: An existing connection was forcibly closed by the remote host.  category="Connection:handleIOError" elapsed="0 ms" goroutine=46

and the unclean close if you remove the sleep.

INFO[0000] :: Running setup                              source=console
WARN[0002] url:https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png method:GET err:error fetching response body: context canceled  category="Response:bodySize:fetchBody" elapsed="0 ms" goroutine=71
WARN[0002] url:https://fonts.gstatic.com/s/i/productlogos/googleg/v6/24px.svg method:GET err:error fetching response body: context canceled  category="Response:bodySize:fetchBody" elapsed="0 ms" goroutine=71
ERRO[0002] err:write tcp 127.0.0.1:51279->127.0.0.1:51278: wsasend: An established connection was aborted by the software in your host machine.  category="Connection:handleIOError" elapsed="0 ms" goroutine=44

EDIT: Made the code simpler
EDIT2: This is using release 0.3
EDIT3: On Windows Server 2016 Data Center

1 Like

@inanc Is it at all reproducable on your side with the minimal example?

I’ll try working on this tomorrow, and let you know :slight_smile: Thanks for the example!

1 Like

Hi @Goodgive,

I tried your script and did not get the “forcibly closed” error :frowning: I’m suspicious of your network settings :thinking: Could you check?

Could you also run the script with the XK6_BROWSER_LOG=trace environment variable?

Thanks

I ran the test locally on my own machine and it does work fine there.
On the DataCenter Server I get the following trace (a subset):

DEBU[0028] running thresholds                            component=metrics-engine metric_name="http_req_duration{staticAsset:yes}"
DEBU[0030] running thresholds                            component=metrics-engine metric_name=http_req_duration
DEBU[0030] running thresholds                            component=metrics-engine metric_name="http_req_duration{staticAsset:yes}"
DEBU[0030] wsURL:"ws://127.0.0.1:65294/devtools/browser/470c15b2-c297-461e-a420-bbbf7eb9a338" ioErr:read tcp 127.0.0.1:65295->127.0.0.1:65294: wsarecv: An existing connection was forcibly closed by the remote host.  category="Connection:recvLoop" elapsed="19193 ms" goroutine=51
ERRO[0030] err:read tcp 127.0.0.1:65295->127.0.0.1:65294: wsarecv: An existing connection was forcibly closed by the remote host.  category="Connection:handleIOError" elapsed="41 ms" goroutine=51
DEBU[0030] code:1001                                     category="Connection:handleIOError:c.closeCh <-" elapsed="3 ms" goroutine=51
DEBU[0030] wsURL:"ws://127.0.0.1:65294/devtools/browser/470c15b2-c297-461e-a420-bbbf7eb9a338" code:1001  category="Connection:sendLoop:<-c.closeCh" elapsed="9 ms" goroutine=52
DEBU[0030] code:1001                                     category="Connection:closeConnection" elapsed="6 ms" goroutine=52
DEBU[0030] sid:EA6E0382352DBFB3E7CA4984518878AB tid:BDCB2C951A04997FB5BE172B59A3587E  category="Session:close" elapsed="6 ms" goroutine=52
DEBU[0030] sid:F909FE0D2F82C3777B70EAF0BCC6B683 tid:0E295D7D8838B74BC238F53179DF2D70  category="Session:close" elapsed="15 ms" goroutine=52
DEBU[0030] sid:EA6E0382352DBFB3E7CA4984518878AB tid:BDCB2C951A04997FB5BE172B59A3587E  category="Session:readLoop:<-s.done" elapsed="6 ms" goroutine=59
DEBU[0030] sid:EA6E0382352DBFB3E7CA4984518878AB tid:BDCB2C951A04997FB5BE172B59A3587E  category="FrameSession:initEvents:go:session.done" elapsed="5 ms" goroutine=70
DEBU[0030] sid:EA6E0382352DBFB3E7CA4984518878AB tid:BDCB2C951A04997FB5BE172B59A3587E  category="NewFrameSession:initEvents:go:return" elapsed="6 ms" goroutine=70
DEBU[0030] sid:F909FE0D2F82C3777B70EAF0BCC6B683 tid:0E295D7D8838B74BC238F53179DF2D70  category="FrameSession:initEvents:go:session.done" elapsed="4 ms" goroutine=143
DEBU[0030] sid:F909FE0D2F82C3777B70EAF0BCC6B683 tid:0E295D7D8838B74BC238F53179DF2D70  category="Session:readLoop:<-s.done" elapsed="5 ms" goroutine=64
DEBU[0030]                                               category="Browser:initEvents:EventConnectionClose" elapsed="3 ms" goroutine=54
DEBU[0030] sid:F909FE0D2F82C3777B70EAF0BCC6B683 tid:0E295D7D8838B74BC238F53179DF2D70  category="NewFrameSession:initEvents:go:return" elapsed="6 ms" goroutine=143
DEBU[0032] running thresholds                            component=metrics-engine metric_name=http_req_duration
DEBU[0032] running thresholds                            component=metrics-engine metric_name="http_req_duration{staticAsset:yes}"
1 Like

The full script I ran on both machines.

import { sleep } from "k6";
import launcher from "k6/x/browser";

export let options = {
  stages: [
    { target: 1, duration: '60s' }
  ],
  thresholds: {
      "http_req_duration": ["p(95)<500"],
      "http_req_duration{staticAsset:yes}": ["p(99)<250"],
  },
}

export default function(data) {
  const browser = launcher.launch('chromium', {headless: true})
  const context = browser.newContext({
  })
  context.setDefaultNavigationTimeout(60)
  context.setDefaultTimeout(60)
  const page = context.newPage()
  console.log("goto page")
  page.goto('https://www.google.com/', { waitUntil: 'load' }) // Start at start page
  console.log("sleep")
  sleep(40)
  page.close()
  browser.close()
}
1 Like

It would be helpfull if K6 could output a bit more about the reason?
Does it have something to do with TLS versioning perhaps?
Is it the ws connection to devtools that closes the connection and devtools is the “remote host” or is it the remote site that does it?

1 Like