openvibers/openrestream Commits
Loopback /metrics (Track O): openvibe-shared/metrics on openre-api (request rates and latencies, process metrics, release_info) plus openre_sessions{state} for starting and live ingest sessions
Changes
@@@ -16,6 +16,11 @@ function createApp({ rt, auth, keys, log = console, fetchImpl }) {const app = express();app.disable('x-powered-by');app.set('trust proxy', config.trustProxy);++ // GET /metrics (loopback only, Track O): request rates and latencies, process metrics and live++ // sessions by state, from openvibe-shared/metrics (mounted before every route).++ const metrics = require('openvibe-shared/metrics').instrument(app, { service: 'openre' });++ metrics.registry.gauge({ name: 'openre_sessions', help: 'Ingest sessions by state', labelNames: ['state'],++ collect: () => db.prepare("SELECT state, count(*) AS n FROM ingest_sessions WHERE state IN ('starting','live') GROUP BY state").all().map((r) => ({ labels: { state: r.state }, value: r.n })) });app.use(contracts.http.middleware());app.use((req, res, next) => {res.setHeader('X-Content-Type-Options', 'nosniff');@@@ -41,10 +46,11 @@ function createApp({ rt, auth, keys, log = console, fetchImpl }) {// A release directory (/opt/openre.stream/releases/<sha>) is named by its commit and has no .git of its own.const releaseRoot = require('path').join(__dirname, '..');const commit = [process.env.RELEASE_COMMIT, config.release, require('path').basename(releaseRoot)].find((v) => /^[0-9a-f]{7,40}$/.test(String(v || '')));-- require('openvibe-shared/release').createRelease({++ const release = require('openvibe-shared/release').createRelease({service: 'openre', root: releaseRoot, packages: ['openvibe-shared', 'openvibe-sdk', 'openvibe-contracts'],env: commit ? { ...process.env, RELEASE_COMMIT: commit } : process.env,-- }).mount(app);++ });++ release.mount(app);// Ready = the database answers and the Network key is loaded. Worker and coordinator state is// reported, not required: the API serves reads while a worker generation rolls over.@@@ -69,6 +69,8 @@ t('openre-api in a drill: reads work and match a normal instance; writes, /play/const rel = await request(normal.base, 'GET', '/release.json');assert.strictEqual(rel.status, 200, 'the release manifest (D43) is served');assert.strictEqual((rel.json || JSON.parse(rel.text || rel.body || '{}')).service, 'openre');++ const met = await request(normal.base, 'GET', '/metrics');++ assert.strictEqual(met.status, 200, 'loopback /metrics (Track O)');const health = await request(normal.base, 'GET', '/api/health');const list = await request(normal.base, 'GET', '/api/v1/streams', { token: reader });const outboxBefore = normal.rt.db.prepare('SELECT count(*) AS n FROM event_outbox').get().n;
@@ -16,6 +16,11 @@ function createApp({ rt, auth, keys, log = console, fetchImpl }) {
@@ -16,6 +16,11 @@ function createApp({ rt, auth, keys, log = console, fetchImpl }) {
const app = express();
const app = express();
app.disable('x-powered-by');
app.disable('x-powered-by');
app.set('trust proxy', config.trustProxy);
app.set('trust proxy', config.trustProxy);
+ // GET /metrics (loopback only, Track O): request rates and latencies, process metrics and live
+ // sessions by state, from openvibe-shared/metrics (mounted before every route).
+ const metrics = require('openvibe-shared/metrics').instrument(app, { service: 'openre' });
+ metrics.registry.gauge({ name: 'openre_sessions', help: 'Ingest sessions by state', labelNames: ['state'],
+ collect: () => db.prepare("SELECT state, count(*) AS n FROM ingest_sessions WHERE state IN ('starting','live') GROUP BY state").all().map((r) => ({ labels: { state: r.state }, value: r.n })) });
app.use(contracts.http.middleware());
app.use(contracts.http.middleware());
app.use((req, res, next) => {
app.use((req, res, next) => {
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('X-Content-Type-Options', 'nosniff');
@@ -41,10 +46,11 @@ function createApp({ rt, auth, keys, log = console, fetchImpl }) {
@@ -41,10 +46,11 @@ function createApp({ rt, auth, keys, log = console, fetchImpl }) {
// A release directory (/opt/openre.stream/releases/<sha>) is named by its commit and has no .git of its own.
// A release directory (/opt/openre.stream/releases/<sha>) is named by its commit and has no .git of its own.
const releaseRoot = require('path').join(__dirname, '..');
const releaseRoot = require('path').join(__dirname, '..');
const commit = [process.env.RELEASE_COMMIT, config.release, require('path').basename(releaseRoot)].find((v) => /^[0-9a-f]{7,40}$/.test(String(v || '')));
const commit = [process.env.RELEASE_COMMIT, config.release, require('path').basename(releaseRoot)].find((v) => /^[0-9a-f]{7,40}$/.test(String(v || '')));
- require('openvibe-shared/release').createRelease({
+ const release = require('openvibe-shared/release').createRelease({
service: 'openre', root: releaseRoot, packages: ['openvibe-shared', 'openvibe-sdk', 'openvibe-contracts'],
service: 'openre', root: releaseRoot, packages: ['openvibe-shared', 'openvibe-sdk', 'openvibe-contracts'],
env: commit ? { ...process.env, RELEASE_COMMIT: commit } : process.env,
env: commit ? { ...process.env, RELEASE_COMMIT: commit } : process.env,
- }).mount(app);
+ });
+ release.mount(app);
// Ready = the database answers and the Network key is loaded. Worker and coordinator state is
// Ready = the database answers and the Network key is loaded. Worker and coordinator state is
// reported, not required: the API serves reads while a worker generation rolls over.
// reported, not required: the API serves reads while a worker generation rolls over.
@@ -69,6 +69,8 @@ t('openre-api in a drill: reads work and match a normal instance; writes, /play/
@@ -69,6 +69,8 @@ t('openre-api in a drill: reads work and match a normal instance; writes, /play/
const rel = await request(normal.base, 'GET', '/release.json');
const rel = await request(normal.base, 'GET', '/release.json');
assert.strictEqual(rel.status, 200, 'the release manifest (D43) is served');
assert.strictEqual(rel.status, 200, 'the release manifest (D43) is served');
assert.strictEqual((rel.json || JSON.parse(rel.text || rel.body || '{}')).service, 'openre');
assert.strictEqual((rel.json || JSON.parse(rel.text || rel.body || '{}')).service, 'openre');
+ const met = await request(normal.base, 'GET', '/metrics');
+ assert.strictEqual(met.status, 200, 'loopback /metrics (Track O)');
const health = await request(normal.base, 'GET', '/api/health');
const health = await request(normal.base, 'GET', '/api/health');
const list = await request(normal.base, 'GET', '/api/v1/streams', { token: reader });
const list = await request(normal.base, 'GET', '/api/v1/streams', { token: reader });
const outboxBefore = normal.rt.db.prepare('SELECT count(*) AS n FROM event_outbox').get().n;
const outboxBefore = normal.rt.db.prepare('SELECT count(*) AS n FROM event_outbox').get().n;