mirror of https://github.com/grafana/grafana
devenv: better loki environment (#49383)
* devenv: rename loki to loki-promtail * devenv: new loki devenv entry with fake data generationpull/49629/head
parent
b07904fe56
commit
ebc20849bd
@ -0,0 +1,14 @@ |
||||
# datasource URL: http://localhost:3100/ |
||||
loki: |
||||
image: grafana/loki:latest |
||||
ports: |
||||
- "3100:3100" |
||||
command: -config.file=/etc/loki/local-config.yaml |
||||
promtail: |
||||
image: grafana/promtail:latest |
||||
volumes: |
||||
- ./docker/blocks/loki-promtail/promtail-config.yaml:/etc/promtail/docker-config.yaml |
||||
- /var/log:/var/log |
||||
- ../data/log:/var/log/grafana |
||||
command: |
||||
-config.file=/etc/promtail/docker-config.yaml |
@ -0,0 +1,3 @@ |
||||
FROM node:16-alpine |
||||
|
||||
COPY data.js /home/node/data.js |
@ -0,0 +1,107 @@ |
||||
const http = require('http'); |
||||
|
||||
if (process.argv.length !== 3) { |
||||
throw new Error('invalid command line: use node sendLogs.js LOKIC_BASE_URL'); |
||||
} |
||||
|
||||
const LOKI_BASE_URL = process.argv[2]; |
||||
|
||||
// helper function, do a http request
|
||||
async function jsonRequest(data, method, url, expectedStatusCode) { |
||||
return new Promise((resolve, reject) => { |
||||
const req = http.request( |
||||
{ |
||||
protocol: url.protocol, |
||||
host: url.hostname, |
||||
port: url.port, |
||||
path: `${url.pathname}${url.search}`, |
||||
method, |
||||
headers: { 'content-type': 'application/json' }, |
||||
}, |
||||
(res) => { |
||||
if (res.statusCode !== expectedStatusCode) { |
||||
reject(new Error(`Invalid response: ${res.statusCode}`)); |
||||
} else { |
||||
resolve(); |
||||
} |
||||
} |
||||
); |
||||
|
||||
req.on('error', (err) => reject(err)); |
||||
|
||||
req.write(JSON.stringify(data)); |
||||
req.end(); |
||||
}); |
||||
} |
||||
|
||||
// helper function, choose a random element from an array
|
||||
function chooseRandomElement(items) { |
||||
const index = Math.trunc(Math.random() * items.length); |
||||
return items[index]; |
||||
} |
||||
|
||||
// helper function, sleep for a duration
|
||||
async function sleep(duration) { |
||||
return new Promise((resolve) => { |
||||
setTimeout(resolve, duration); |
||||
}); |
||||
} |
||||
|
||||
async function lokiSendLogLine(timestampMs, line, tags) { |
||||
// we keep nanosecond-timestamp in a string because
|
||||
// as a number it would be too large
|
||||
const timestampNs = `${timestampMs}000000`; |
||||
const data = { |
||||
streams: [ |
||||
{ |
||||
stream: tags, |
||||
values: [[timestampNs, line]], |
||||
}, |
||||
], |
||||
}; |
||||
|
||||
const url = new URL(LOKI_BASE_URL); |
||||
url.pathname = '/loki/api/v1/push'; |
||||
|
||||
await jsonRequest(data, 'POST', url, 204); |
||||
} |
||||
|
||||
function getRandomLogLine(counter) { |
||||
const randomText = `${Math.trunc(Math.random() * 1000 * 1000 * 1000)}`; |
||||
const maybeAnsiText = Math.random() < 0.5 ? 'with ANSI \u001b[31mpart of the text\u001b[0m' : ''; |
||||
return JSON.stringify({ |
||||
_entry: `log text ${maybeAnsiText} [${randomText}]`, |
||||
counter: counter.toString(), |
||||
float: Math.random() > 0.2 ? (100 * Math.random()).toString() : 'NaN', |
||||
label: chooseRandomElement(['val1', 'val2', 'val3']), |
||||
level: chooseRandomElement(['info', 'info', 'error']), |
||||
}); |
||||
} |
||||
|
||||
const SLEEP_ANGLE_STEP = Math.PI / 200; |
||||
let sleepAngle = 0; |
||||
function getNextSineWaveSleepDuration() { |
||||
sleepAngle += SLEEP_ANGLE_STEP; |
||||
return Math.trunc(1000 * Math.abs(Math.sin(sleepAngle))); |
||||
} |
||||
|
||||
async function main() { |
||||
const tags = { |
||||
place: 'moon', |
||||
}; |
||||
|
||||
for (let step = 0; step < 300; step++) { |
||||
await sleep(getNextSineWaveSleepDuration()); |
||||
const timestampMs = new Date().getTime(); |
||||
const line = getRandomLogLine(step + 1); |
||||
lokiSendLogLine(timestampMs, line, tags); |
||||
} |
||||
} |
||||
|
||||
// when running in docker, we catch the needed stop-signal, to shutdown fast
|
||||
process.on('SIGTERM', () => { |
||||
console.log('shutdown requested'); |
||||
process.exit(0); |
||||
}); |
||||
|
||||
main(); |
@ -1,14 +1,13 @@ |
||||
# datasource URL: http://localhost:3100/ |
||||
loki: |
||||
image: grafana/loki:latest |
||||
ports: |
||||
- "3100:3100" |
||||
command: -config.file=/etc/loki/local-config.yaml |
||||
promtail: |
||||
image: grafana/promtail:latest |
||||
volumes: |
||||
- ./docker/blocks/loki/promtail-config.yaml:/etc/promtail/docker-config.yaml |
||||
- /var/log:/var/log |
||||
- ../data/log:/var/log/grafana |
||||
command: |
||||
-config.file=/etc/promtail/docker-config.yaml |
||||
|
||||
data: |
||||
build: docker/blocks/loki/data |
||||
command: node /home/node/data.js http://loki:3100 |
||||
depends_on: |
||||
- loki |
||||
# when loki starts, there might be some time while it is not |
||||
# accepting requests, so we allow data.js to restart on failure. |
||||
restart: "on-failure" |
Loading…
Reference in new issue