All files / servicesExternal LogtailService.js

35.89% Statements 28/78
60% Branches 3/5
40% Functions 2/5
35.89% Lines 28/78

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 781x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x             1x 1x 1x 1x 1x 1x 1x                 1x 1x                           1x 1x                                               1x
import axios from "axios";
import {isSet, nowISO8601, nowMinusHoursUTCISO, toHuman, toHumanDay, toHumanTime} from "../lib/Common.js";
import {NEWS_LABEL} from "../services/NewsService.js";
 
/**
 * autonomous gist : https://gist.github.com/boly38/e853a1d83b63481fd5a97e4b7822813e
 */
export default class LogtailService {
    constructor(config, loggerService) {
        this.config = config;
        this.tz = config.tz;
        this.logger = loggerService.getLogger().child({label: 'LogtailService'});
        this.logtail_api_v1 = config.log?.logtailApiV1;
        this.logtail_api_token = config.log?.logtailApiToken;
        this.logtail_source_id = config.log?.logtailSourceId;
        if (isSet(this.logtail_api_v1) && isSet(this.logtail_api_token) && isSet(this.logtail_source_id)) {
            this.logtailClient = axios.create({
                baseURL: this.logtail_api_v1,
                timeout: 30000,
                headers: {'Authorization': `Bearer ${this.logtail_api_token}`}
            });
        }
    }
 
    isAvailable() {
        return isSet(this.logtailClient);
    }
 
    querySource(sourceIds/* coma separated ids */, query, from, to, batch = 100) {
        const service = this;
        return new Promise((resolve, reject) => {
            // query source(s) - https://betterstack.com/docs/logs/query-api/
            service.logtailClient.get('/query', {params: {source_ids: sourceIds, query, from, to, batch}})
                .then(res => resolve(res?.data))
                .catch(res => reject(res));
        });
    }
 
    perDateMessage(logs) {
        const {tz} = this
        const resultMap = {};
        logs.forEach(d => {
            const dt = toHumanTime(d.dt, tz);
            const day = toHumanDay(d.dt, tz);
            const message = d.message;
            if (!resultMap[day]) {
                resultMap[day] = [];
            }
            resultMap[day].push({dt,message});
        });
        return resultMap;
    }
 
    getRecentNews() {
        const service = this;
        const {logger, tz} = this
        return new Promise((resolve, reject) => {
            const logtail_source_id = this.logtail_source_id;
            const from = nowMinusHoursUTCISO(3 * 24);//now - 3 days
            const to = nowISO8601();//now
            // query syntax : https://betterstack.com/docs/logs/using-logtail/live-tail-query-language/
            const query = `label:"${NEWS_LABEL}"`;
            logger.debug(`querySource id=${logtail_source_id}, query=${query}, from=${from} to=${to} tz=${tz}`);
            service.querySource(logtail_source_id, query, from, to)
                .then(result => {
                    const data = this.perDateMessage(result.data);
                    const logtailNews = {
                        "from": toHuman(from, tz),
                        "to": toHuman(to, tz),
                        data
                    };
                    logger.debug(`result news ${logtailNews.data?.length}`);
                    resolve(logtailNews);
                })
                .catch(reject);
        });
    }
}