mirror of
https://github.com/Retropex/apolloapi-v2.git
synced 2025-05-28 13:02:35 +02:00
Added Ckpool stats
This commit is contained in:
parent
e1b6389a9c
commit
664d4a8ed4
@ -2,7 +2,6 @@ const path = require('path')
|
||||
const express = require('express')
|
||||
const cors = require('cors');
|
||||
const graphqlApp = require('./graphqlApp')
|
||||
const buildPath = path.join(__dirname, '../../apolloui/build');
|
||||
|
||||
const app = express()
|
||||
|
||||
@ -10,11 +9,4 @@ app.use(cors());
|
||||
|
||||
app.use('/api/graphql', graphqlApp)
|
||||
|
||||
if (process.env.NODE_ENV === 'production') app.use(express.static(buildPath));
|
||||
|
||||
app.get('*', function (req, res) {
|
||||
if (process.env.NODE_ENV === 'production') res.sendFile(buildPath + '/index.html');
|
||||
else res.json({ message: 'API DEV server running' })
|
||||
});
|
||||
|
||||
module.exports = app
|
||||
|
@ -23,6 +23,7 @@ module.exports.typeDefs = `
|
||||
temperature: MinerStatsTemperature
|
||||
slots: MinerStatsSlots
|
||||
slaves: [MinerStatsSlave]
|
||||
ckpool: MinerStatsCkpool
|
||||
}
|
||||
|
||||
type MinerStatsVersion {
|
||||
@ -160,7 +161,7 @@ module.exports.typeDefs = `
|
||||
errorRate: Float
|
||||
chipRestarts: Int
|
||||
wattPerGHs: Float
|
||||
tmpAlert: [MinerStatsSlotAlert],
|
||||
tmpAlert: [MinerStatsSlotAlert]
|
||||
osc: Int
|
||||
oscStopChip: String
|
||||
}
|
||||
@ -181,12 +182,68 @@ module.exports.typeDefs = `
|
||||
ping: Int
|
||||
}
|
||||
|
||||
`
|
||||
type MinerStatsCkpool {
|
||||
pool: MinerStatsCkpoolPool
|
||||
users: MinerStatsCkpoolUsers
|
||||
}
|
||||
|
||||
type MinerStatsCkpoolPool {
|
||||
runtime: Int
|
||||
lastupdate: Int
|
||||
Users: Int
|
||||
Workers: Int
|
||||
Idle: Int
|
||||
Disconnected: Int
|
||||
hashrate1m: String
|
||||
hashrate5m: String
|
||||
hashrate15m: String
|
||||
hashrate1hr: String
|
||||
hashrate6hr: String
|
||||
hashrate1d: String
|
||||
hashrate7d: String
|
||||
diff: Int
|
||||
accepted: Int
|
||||
rejected: Int
|
||||
bestshare: Int
|
||||
SPS1m: Float
|
||||
SPS5m: Float
|
||||
SPS15m: Float
|
||||
SPS1h: Float
|
||||
}
|
||||
|
||||
type MinerStatsCkpoolUsers {
|
||||
hashrate1m: String
|
||||
hashrate5m: String
|
||||
hashrate1hr: String
|
||||
hashrate1d: String
|
||||
hashrate7d: String
|
||||
lastshare: Int
|
||||
workers: Int
|
||||
shares: Int
|
||||
bestshare: Float
|
||||
bestever: Int
|
||||
authorised: Int
|
||||
worker: [MinerStatsCkpoolWorker]
|
||||
}
|
||||
|
||||
type MinerStatsCkpoolWorker {
|
||||
workername: String,
|
||||
hashrate1m: String,
|
||||
hashrate5m: String,
|
||||
hashrate1hr: String,
|
||||
hashrate1d: String,
|
||||
hashrate7d: String,
|
||||
lastshare: Int,
|
||||
shares: Int,
|
||||
bestshare: Float,
|
||||
bestever: Int
|
||||
}
|
||||
`;
|
||||
|
||||
module.exports.resolvers = {
|
||||
MinerActions: {
|
||||
stats (root, args, { dispatch }) {
|
||||
return dispatch('api/miner/stats')
|
||||
stats(root, args, { dispatch }) {
|
||||
return dispatch('api/miner/stats');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1,73 +1,169 @@
|
||||
const { join } = require('path')
|
||||
const { exec } = require('child_process')
|
||||
const fs = require('fs').promises
|
||||
const path = require('path')
|
||||
const _ = require('lodash')
|
||||
const moment = require('moment')
|
||||
const { join } = require('path');
|
||||
const { exec } = require('child_process');
|
||||
const fs = require('fs').promises;
|
||||
const path = require('path');
|
||||
const _ = require('lodash');
|
||||
const moment = require('moment');
|
||||
const { existsSync } = require('fs');
|
||||
const c = require('config');
|
||||
|
||||
module.exports = ({ define }) => {
|
||||
define('stats', async (payload, { knex, errors, utils }) => {
|
||||
const stats = await getMinerStats(errors)
|
||||
return { stats }
|
||||
}, {
|
||||
auth: true
|
||||
})
|
||||
define(
|
||||
'stats',
|
||||
async (payload, { knex, errors, dispatch }) => {
|
||||
const settings = await dispatch('api/settings/collection/read');
|
||||
const { items: pools } = await dispatch('api/pools/collection/read', {});
|
||||
const stats = await getMinerStats(errors, settings, pools);
|
||||
return { stats };
|
||||
},
|
||||
{
|
||||
auth: true,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const parseFileToJsonArray = async (filePath) => {
|
||||
try {
|
||||
// Read the file content
|
||||
const fileContent = await fs.readFile(filePath, 'utf8');
|
||||
|
||||
// Divide the file content into lines
|
||||
const lines = fileContent.split('\n');
|
||||
|
||||
const allKeys = {};
|
||||
|
||||
// Analyze each line
|
||||
lines.forEach(line => {
|
||||
if (line.trim() !== '') {
|
||||
try {
|
||||
const jsonObject = JSON.parse(line);
|
||||
|
||||
// Add the keys to the allKeys object
|
||||
Object.entries(jsonObject).forEach(([key, value]) => {
|
||||
if (!allKeys[key]) {
|
||||
allKeys[key] = null;
|
||||
}
|
||||
allKeys[key] = value;
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(`Error during the parsing of the line: ${error.message}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return allKeys;
|
||||
} catch (error) {
|
||||
console.error(`Error during the reading of the file: ${error.message}`);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
async function getMinerStats (errors) {
|
||||
const getMinerStats = async (errors, settings, pools) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
(async () => {
|
||||
(async () => {
|
||||
try {
|
||||
const statsDir = path.resolve(__dirname, '../../../../backend/apollo-miner/');
|
||||
const statsDir = path.resolve(
|
||||
__dirname,
|
||||
'../../../../backend/apollo-miner/'
|
||||
);
|
||||
const statsFilePattern = 'apollo-miner.*';
|
||||
let statsFiles = await fs.readdir(statsDir);
|
||||
statsFiles = _.filter(statsFiles, (f) => { return f.match(statsFilePattern) })
|
||||
statsFiles = _.filter(statsFiles, (f) => {
|
||||
return f.match(statsFilePattern);
|
||||
});
|
||||
|
||||
// Get ckpool data
|
||||
let ckpoolData = null;
|
||||
|
||||
if (settings?.nodeEnableSoloMining) {
|
||||
const poolUsername = pools[0] && pools[0].username;
|
||||
const ckpoolPoolStatsFile = path.resolve(
|
||||
__dirname,
|
||||
'../../../../backend/ckpool/logs/pool/pool.status'
|
||||
);
|
||||
|
||||
const ckpoolUsersStatsFile = path.resolve(
|
||||
__dirname,
|
||||
`../../../../backend/ckpool/logs/users/${poolUsername}`
|
||||
);
|
||||
|
||||
if (
|
||||
existsSync(ckpoolPoolStatsFile) &&
|
||||
existsSync(ckpoolUsersStatsFile)
|
||||
) {
|
||||
await Promise.all([
|
||||
(async () => {
|
||||
let ckpoolPoolData = await parseFileToJsonArray(ckpoolPoolStatsFile);
|
||||
let ckpoolUsersData = await fs.readFile(ckpoolUsersStatsFile, 'utf8');
|
||||
|
||||
ckpoolUsersData = JSON.parse(ckpoolUsersData);
|
||||
|
||||
ckpoolData = {
|
||||
pool: ckpoolPoolData,
|
||||
users: ckpoolUsersData,
|
||||
};
|
||||
})(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
let stats = [];
|
||||
|
||||
await Promise.all(statsFiles.map(async (file) => {
|
||||
const data = await fs.readFile(`${statsDir}/${file}`);
|
||||
let received = data.toString('utf8').trim();
|
||||
// JSON from miner is dirty, clean it
|
||||
received = received
|
||||
.replace(/\-nan/g, '0')
|
||||
.replace(/[^\x00-\x7F]/g, '')
|
||||
.replace('}{', '},{')
|
||||
.replace(String.fromCharCode(0), '')
|
||||
.replace(/[^\}]+$/, '')
|
||||
await Promise.all(
|
||||
statsFiles.map(async (file) => {
|
||||
const data = await fs.readFile(`${statsDir}/${file}`);
|
||||
let received = data.toString('utf8').trim();
|
||||
// JSON from miner is dirty, clean it
|
||||
received = received
|
||||
.replace(/\-nan/g, '0')
|
||||
.replace(/[^\x00-\x7F]/g, '')
|
||||
.replace('}{', '},{')
|
||||
.replace(String.fromCharCode(0), '')
|
||||
.replace(/[^\}]+$/, '');
|
||||
|
||||
received = JSON.parse(received);
|
||||
received = JSON.parse(received);
|
||||
|
||||
received.uuid = file.replace('apollo-miner.', '');
|
||||
received.uuid = file.replace('apollo-miner.', '');
|
||||
|
||||
received.master.intervals = _.mapKeys(received.master.intervals, (value, name) => {
|
||||
return `int_${name}`
|
||||
});
|
||||
received.master.intervals = _.mapKeys(
|
||||
received.master.intervals,
|
||||
(value, name) => {
|
||||
return `int_${name}`;
|
||||
}
|
||||
);
|
||||
|
||||
received.pool.intervals = _.mapKeys(received.pool.intervals, (value, name) => {
|
||||
return `int_${name}`
|
||||
});
|
||||
received.pool.intervals = _.mapKeys(
|
||||
received.pool.intervals,
|
||||
(value, name) => {
|
||||
return `int_${name}`;
|
||||
}
|
||||
);
|
||||
|
||||
received.fans = _.mapKeys(received.fans, (value, name) => {
|
||||
return `int_${name}`
|
||||
});
|
||||
received.fans = _.mapKeys(received.fans, (value, name) => {
|
||||
return `int_${name}`;
|
||||
});
|
||||
|
||||
received.slots = _.mapKeys(received.slots, (value, name) => {
|
||||
return `int_${name}`
|
||||
});
|
||||
received.slots = _.mapKeys(received.slots, (value, name) => {
|
||||
return `int_${name}`;
|
||||
});
|
||||
|
||||
// Hack to add timezone to miner date
|
||||
let offset = new Date().getTimezoneOffset();
|
||||
offset *= -1
|
||||
received.date = moment(`${received.date}`, 'YYYY-MM-DD HH:mm:ss').utcOffset(offset).format();
|
||||
// Hack to add timezone to miner date
|
||||
let offset = new Date().getTimezoneOffset();
|
||||
offset *= -1;
|
||||
received.date = moment(`${received.date}`, 'YYYY-MM-DD HH:mm:ss')
|
||||
.utcOffset(offset)
|
||||
.format();
|
||||
|
||||
stats.push(received);
|
||||
}));
|
||||
if (ckpoolData) received.ckpool = ckpoolData;
|
||||
|
||||
resolve(stats)
|
||||
stats.push(received);
|
||||
})
|
||||
);
|
||||
|
||||
resolve(stats);
|
||||
} catch (err) {
|
||||
reject(new errors.InternalError(err.toString()));
|
||||
}
|
||||
})()
|
||||
})();
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user