# [[xk6-loki]] ![[xk6-loki.svg]] [repo](https://github.com/grafana/xk6-loki) xk6-loki is an [[Extensions for k6 using xk6|extension]] for [[k6 (tool)|k6]] that allows you to create scripts to push [[Logs]] to [[Grafana Loki|Loki]]. Using xk6-loki, you can [send k6 logs to Loki](https://k6.io/blog/using-loki-to-store-and-query-k6-logs/) or [load test your Loki installation](https://grafana.com/docs/loki/latest/send-data/k6/). Here's a quick script that you can use to do this: ```javascript import {sleep, check} from 'k6'; import loki from 'k6/x/loki'; /** * URL used for push and query requests * Path is automatically appended by the client * @constant {string} */ const username = '<USERNAME>'; const password = '<PASSWORD>'; const external_ip = '<EXTERNAL-IP>'; const credentials = `${username}:${password}`; const BASE_URL = `http://${credentials}@${external_ip}`; /** * Helper constant for byte values * @constant {number} */ const KB = 1024; /** * Helper constant for byte values * @constant {number} */ const MB = KB * KB; /** * Instantiate config and Loki client */ const conf = new loki.Config(BASE_URL); const client = new loki.Client(conf); /** * Define test scenario */ export const options = { vus: 10, iterations: 10, }; export default () => { // Push request with 10 streams and uncompressed logs between 800KB and 2MB var res = client.pushParameterized(10, 800 * KB, 2 * MB); // Check for successful write check(res, { 'successful write': (res) => res.status == 204 }); // Pick a random log format from label pool let format = randomChoice(conf.labels["format"]); // Execute instant query with limit 1 res = client.instantQuery(`count_over_time({format="${format}"}[1m])`, 1) // Check for successful read check(res, { 'successful instant query': (res) => res.status == 200 }); // Execute range query over last 5m and limit 1000 res = client.rangeQuery(`{format="${format}"}`, "5m", 1000) // Check for successful read check(res, { 'successful range query': (res) => res.status == 200 }); // Wait before next iteration sleep(1); } /** * Helper function to get random item from array */ function randomChoice(items) { return items[Math.floor(Math.random() * items.length)]; } ``` Replace `<EXTERNAL-IP>` with the external IP address of the Loki Gateway service and `<USERNAME>` and `PASSWORD` with the credentials required to access Loki (if required). %% # Excalidraw Data ## Text Elements ## Drawing ```json { "type": "excalidraw", "version": 2, "source": "https://github.com/zsviczian/obsidian-excalidraw-plugin/releases/tag/2.1.4", "elements": [ { "id": "4y8R7iOA", "type": "text", "x": 118.49495565891266, "y": -333.44393157958984, "width": 3.8599853515625, "height": 24, "angle": 0, "strokeColor": "#1e1e1e", "backgroundColor": "transparent", "fillStyle": "solid", "strokeWidth": 2, "strokeStyle": "solid", "roughness": 1, "opacity": 100, "groupIds": [], "frameId": null, "roundness": null, "seed": 967149026, "version": 2, "versionNonce": 939059582, "isDeleted": true, "boundElements": null, "updated": 1713723615080, "link": null, "locked": false, "text": "", "rawText": "", "fontSize": 20, "fontFamily": 4, "textAlign": "left", "verticalAlign": "top", "containerId": null, "originalText": "", "lineHeight": 1.2 } ], "appState": { "theme": "dark", "viewBackgroundColor": "#ffffff", "currentItemStrokeColor": "#1e1e1e", "currentItemBackgroundColor": "transparent", "currentItemFillStyle": "solid", "currentItemStrokeWidth": 2, "currentItemStrokeStyle": "solid", "currentItemRoughness": 1, "currentItemOpacity": 100, "currentItemFontFamily": 4, "currentItemFontSize": 20, "currentItemTextAlign": "left", "currentItemStartArrowhead": null, "currentItemEndArrowhead": "arrow", "scrollX": 583.2388916015625, "scrollY": 573.6323852539062, "zoom": { "value": 1 }, "currentItemRoundness": "round", "gridSize": null, "gridColor": { "Bold": "#C9C9C9FF", "Regular": "#EDEDEDFF" }, "currentStrokeOptions": null, "previousGridSize": null, "frameRendering": { "enabled": true, "clip": true, "name": true, "outline": true } }, "files": {} } ``` %%