@platformos/pos-cli
Version:
Manage your platformOS application
284 lines (247 loc) • 8.15 kB
JavaScript
import { fetchSettings } from '../lib/settings.js';
import path from 'path';
import { fileURLToPath } from 'url';
import Gateway from '../lib/proxy.js';
import logger from '../lib/logger.js';
import ServerError from '../lib/ServerError.js';
import api from './logsv2/http.js';
import fs from 'fs';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
class APIs {
constructor(ctx) {
this.Search = new Search(ctx);
this.Alerts = new Alerts(ctx);
}
}
class Alerts {
constructor(ctx) {
this.ctx = ctx;
}
async ListAlerts({org_id}, {securities}) {
return await api.get(this.ctx.url + `/api/${org_id}/alerts`, {
securities: securities
});
}
async TriggerAlert({org_id, stream_name, alert_name}, {requestBody, securities}) {
return await api.put(this.ctx.url + `/api/${org_id}/${stream_name}/alerts/${alert_name}/trigger`, {
securities: securities,
body: requestBody
});
}
async SaveAlert({org_id, stream_name, alert_name}, {requestBody, securities}) {
return await api.post(this.ctx.url + `/api/${org_id}/${stream_name}/alerts/${alert_name}`, {
securities: securities,
body: requestBody
});
}
async CreateTemplate({org_id, template_name}, {requestBody, securities}) {
return await api.post(this.ctx.url + `/api/${org_id}/alerts/templates/${template_name}`, {
securities: securities,
body: requestBody
});
}
async CreateDestination({org_id, destination_name}, {requestBody, securities}) {
return await api.post(this.ctx.url + `/api/${org_id}/alerts/destinations/${destination_name}`, {
securities: securities,
body: requestBody
});
}
}
class Search {
constructor(ctx) {
this.ctx = ctx;
}
async SearchSQL({org_id}, {requestBody, securities}) {
return await api.post(this.ctx.url + `/api/${org_id}/_search`, {
securities: securities,
body: requestBody
});
}
async SearchAround({org_id, stream_name, key, size, sql}, {_requestBody, securities}) {
if (sql == undefined) sql = '';
return await api.get(this.ctx.url + `/api/${org_id}/${stream_name}/_around`, {
securities: securities,
params: { key, size, sql }
});
}
}
class LogClient {
constructor({ url }) {
this.apis = new APIs(this);
this.url = url;
}
}
class SwaggerProxy {
static async client(environment) {
try {
const LOGS_PROXY_URL = process.env.LOGS_PROXY_URL || 'https://openobserve-proxy.platformos.dev';
const client = new LogClient({url: LOGS_PROXY_URL});
const authData = await fetchSettings(environment);
const securities = { authorized: { Authorization: authData.token }};
const instance = await new Gateway(authData).getInstance();
instance.url = authData.url;
logger.Debug({instance, authData, securities});
return new SwaggerProxy(client, instance, securities);
} catch(e) {
if (e.statusCode == 401)
await logger.Error(`[Unauthorized] Please ensure your token is correct.\nTo refresh your token, execute the following command:\npos-cli env refresh-token ${ environment }`);
else if (ServerError.isNetworkError(e))
await ServerError.handler(e);
else
await logger.Error(e.message || e);
}
}
constructor(client, instance, securities) {
this.client = client;
this.instance = instance;
this.securities = securities;
}
async searchAround(program){
return this.client.apis.Search
.SearchAround(
{org_id: this.instance.uuid, stream_name: program.stream_name, key: program.key, size: program.size, sql: program.sql},
{securities: this.securities});
}
async searchSQLByQuery(query){
return this.client.apis.Search
.SearchSQL(
{org_id: this.instance.uuid},
{requestBody: query, securities: this.securities});
}
async searchSQL(program){
return this.searchSQLByQuery(search.buildQuery(program));
}
async alerts(_program){
return this.client.apis.Alerts
.ListAlerts({org_id: this.instance.uuid}, {securities: this.securities});
}
async triggerAlert(program){
return this.client.apis.Alerts
.TriggerAlert(
{org_id: this.instance.uuid, stream_name: 'logs', alert_name: program.name},
{securities: this.securities});
}
async createAlert(program){
const alert = alerts.buildAlert(program);
const template = await this.createTemplate(program);
logger.Debug(template.body);
const destination = await this.createDestination(program);
logger.Debug(destination.body);
return this.client.apis.Alerts
.SaveAlert(
{org_id: this.instance.uuid, stream_name: 'logs', alert_name: program.name},
{requestBody: alert, securities: this.securities});
}
async createDestination(program){
const destination = alerts.buildDestination(program);
logger.Debug(destination);
return this.client.apis.Alerts
.CreateDestination(
{org_id: this.instance.uuid, destination_name: program.name},
{requestBody: destination, securities: this.securities});
}
async createTemplate(program){
program.instance = this.instance;
const template = { name: program.name, body: alerts.templates.slack(program), isDefault: true };
logger.Debug(template);
return this.client.apis.Alerts
.CreateTemplate(
{org_id: this.instance.uuid, template_name: program.name},
{requestBody: template, securities: this.securities});
}
}
const alerts = {
templates: {
slack({_name, operator, keyword, column, channel, instance}) {
const template = JSON.parse(fs.readFileSync(path.join(__dirname, './openobserve/alerts/slack.json')));
template.channel = channel;
const description = `*Alert details:*\n *${column}* column ${operator} *${keyword}* keyword`;
template.text = description;
template.blocks.push({type: 'section', text: {text: description, type: 'mrkdwn'}});
const instanceInfo = `*Instance*:\n ${instance.url}`;
template.blocks.push({type: 'section', text: {text: instanceInfo, type: 'mrkdwn'}});
return template;
}
},
buildDestination({url, name}){
return {
'headers': {
},
'method': 'post',
'name': name,
'skip_tls_verify': false,
'template': name,
'url': url
};
},
buildAlert({_from, name, keyword, _sql, _column, operator}){
return {
'condition': {
'column': 'message',
'ignoreCase': true,
'isNumeric': true,
'operator': operator,
'value': keyword
},
'destination': name,
'duration': 0,
'frequency': 0,
'is_real_time': true,
'name': name,
'time_between_alerts': 0
};
}
};
const search = {
buildQuery({from, size, start_time, end_time, sql}) {
query = {
query: {
from: parseInt(from),
size: parseInt(size),
sql: (sql || 'select * from logs')
}
};
if (start_time) query.query['start_time'] = parseInt(start_time);
if (end_time) query.query['end_time'] = parseInt(end_time);
return query;
},
printJSON: logger.Info,
printLogs(response, key) {
Object
.entries(response.hits)
.map((item) => {
item[1].highlight = item[1]._timestamp.toString() == key;
return item;
})
.forEach(search.printLog);
},
printLog(hit) {
console.log(search.formatHit(hit));
},
formatHit([_id, hit]) {
const row = `[${search.toDate(hit._timestamp)}] ${hit._timestamp} ${hit.type} | ${hit.message}`;
if (hit.highlight) {
return row.blue;
} else {
return row;
}
},
printReport(response, report) {
console.log(report.meta.title);
if (response.aggs)
console.table(
Object.entries(response.aggs.histogram).map((r) => {
return r[1];
}),
report.meta.columns
);
},
toDate(timestamp) {
if (timestamp)
return new Date(timestamp / 1000).toLocaleString();
else
'---';
}
};
export { SwaggerProxy, search };