github.com/grafana/synthetic-monitoring-agent@v0.64.2/internal/prober/multihttp/script.tmpl (about) 1 import http from 'k6/http'; 2 import { check, fail } from 'k6'; 3 import { test } from 'k6/execution'; 4 // TODO(mem): conditionally import these modules 5 // - import encoding if base64 decoding is required 6 // - import jsonpath if there are json assertions 7 import encoding from 'k6/encoding'; 8 import jsonpath from 'https://jslib.k6.io/jsonpath/1.0.2/index.js'; 9 import { URL } from 'https://jslib.k6.io/url/1.0.0/index.js'; 10 11 export const options = { 12 scenarios: { 13 default: { 14 executor: 'shared-iterations', 15 tags: { 16 // TODO(mem): build tags out of options for the check? 17 environment: 'production', 18 }, 19 // exec: 'runner', 20 maxDuration: '10s', // TODO(mem): this would be the timeout for the check 21 gracefulStop: '1s', 22 }, 23 }, 24 25 dns: { 26 ttl: '2m', // TODO(mem): this doesn't need to be much higher than the maxDuration 27 select: 'first', 28 // TODO(mem): we can build this maps to IP option in checks, more or less 29 policy: 'preferIPv4', // preferIPv6, onlyIPv4, onlyIPv6, any 30 }, 31 32 // TODO(mem): we can build this out of check options 33 insecureSkipTLSVerify: false, 34 tlsVersion: { 35 // TODO(mem): we can build this out of check options 36 min: 'tls1.2', 37 max: 'tls1.3', 38 }, 39 // TODO(mem): we can build this out of agent version 40 userAgent: 'synthetic-monitoring-agent/v0.14.3 (linux amd64; g64b8bab; +https://github.com/grafana/synthetic-monitoring-agent)', 41 42 maxRedirects: 10, 43 44 // k6 options 45 vus: 1, 46 // linger: false, 47 summaryTimeUnit: 's', 48 discardResponseBodies: false, // enable only if there are checks? 49 }; 50 51 function assertHeader(headers, name, matcher) { 52 const lcName = name.toLowerCase(); 53 const values = Object.entries(headers). 54 filter(h => h[0].toLowerCase() === lcName). 55 map(h => h[1]); 56 57 if (values.find(v => matcher(v)) !== undefined) { 58 return true; 59 } else if (values.length === 0) { 60 console.warn(`'${name}' not present in response`); 61 } else { 62 values.forEach(v => console.warn(`'${name}' has the value '${v}'`)); 63 } 64 65 return false; 66 } 67 68 export default function() { 69 let response; 70 let body; 71 let url; 72 let currentCheck; 73 let match; 74 const logResponse = {{ .LogResponses }} 75 const vars = {}; 76 77 {{ range $idx, $entry := .Entries }} 78 console.log("Starting request to {{.Request.Url}}..."); 79 try { 80 url = new URL({{ buildUrl .Request.Url }}); 81 } catch(e) { 82 console.error("Invalid URL: {{ .Request.Url }}"); 83 fail() 84 } 85 {{- $queries := buildQueryParams "url" .Request }} 86 {{ range $queries }}{{ . }}; 87 {{ end -}} 88 {{- $method := .Request.Method.String }} 89 90 body = {{ buildBody .Request.Body }}; 91 {{- $bodyVars := interpolateBodyVars "body" .Request.Body }} 92 {{ range $bodyVars }}{{ . }}; 93 {{ end -}} 94 95 {{- $headers := buildHeaders .Request.Headers .Request.Body }} 96 response = http.request('{{ $method }}', url.toString(), body, { 97 // TODO(mem): build params out of options for the check 98 tags: { 99 name: '{{ $idx }}', // TODO(mem): give the user some control over this? 100 __raw_url__: '{{ .Request.Url }}', 101 }, 102 redirects: 0{{ if gt (len $headers) 0 }}, 103 headers: {{ $headers }}{{ end }} 104 }); 105 console.log("Response received from {{ .Request.Url }}, status", response.status); 106 if(logResponse) { 107 const body = response.body || '' 108 console.log("Response body received from {{ .Request.Url }}:", body.slice(0, 1000)); 109 } 110 if(response.error) { 111 console.error("Request error:" + url.toString() + ": " + response.error) 112 } 113 {{ range .Assertions }}{{ buildChecks "url" $method . }} 114 {{ end -}} 115 {{ range .Variables }}{{ buildVars . }} 116 {{ end -}} 117 {{ end }} 118 }