add LoggingProvider
unified interface for console & remote JSON logging! had to write my own as i don't want to send this information through google. fixup! add LoggingProviderios
parent
816d672383
commit
8010bd0a0c
@ -1,4 +1,11 @@
|
||||
import { LogLevel, LogOptions } from "./providers/logging/logging";
|
||||
|
||||
export const COLORS = {
|
||||
PRIMARY: '#4EAF47', // sensebox green
|
||||
}
|
||||
export const DEFAULT_LANG = 'en'
|
||||
export const LOG_OPTIONS: LogOptions = {
|
||||
local: LogLevel.INFO,
|
||||
remote: LogLevel.WARN,
|
||||
endpoint: 'https://logs.snsbx.nroo.de/log',
|
||||
}
|
||||
|
@ -0,0 +1,125 @@
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { AppVersion } from '@ionic-native/app-version/ngx';
|
||||
import { Platform } from 'ionic-angular';
|
||||
|
||||
import { LOG_OPTIONS } from '../../constants';
|
||||
import { StorageProvider, SETTINGS } from '../storage/storage';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
// these types must be defined here to avoid a circular dependency with LoggingProvider
|
||||
export interface LogOptions {
|
||||
local: boolean | LogLevel,
|
||||
remote: boolean | LogLevel,
|
||||
endpoint: string,
|
||||
}
|
||||
export enum LogLevel {
|
||||
DEBUG = 0,
|
||||
INFO = 1,
|
||||
WARN = 2,
|
||||
ERROR = 3,
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class LoggingProvider {
|
||||
private opts: LogOptions = LOG_OPTIONS
|
||||
private defaultFields: any = {}
|
||||
|
||||
constructor(
|
||||
private http: HttpClient,
|
||||
private plt: Platform,
|
||||
private version: AppVersion,
|
||||
private storage: StorageProvider,
|
||||
private translate: TranslateService,
|
||||
) {
|
||||
if ((<any>window).cordova) {
|
||||
this.version.getPackageName()
|
||||
.then(name => this.defaultFields.app = name)
|
||||
this.version.getVersionNumber()
|
||||
.then(version => this.defaultFields.appVersion = version)
|
||||
}
|
||||
this.defaultFields.platform = this.plt.platforms().join(' ')
|
||||
this.defaultFields.platformVersion = this.plt.version().str
|
||||
this.defaultFields.lang = translate.currentLang
|
||||
}
|
||||
|
||||
createChild (component: string, defaultFields: object = {}) {
|
||||
const child = new LoggingProvider(this.http, this.plt, this.version, this.storage, this.translate)
|
||||
Object.assign(child.defaultFields, defaultFields, { component })
|
||||
return child
|
||||
}
|
||||
|
||||
debug (...data) { return this.log(LogLevel.DEBUG, ...data) }
|
||||
info (...data) { return this.log(LogLevel.INFO, ...data) }
|
||||
warn (...data) { return this.log(LogLevel.WARN, ...data) }
|
||||
error (...data) { return this.log(LogLevel.ERROR, ...data) }
|
||||
|
||||
private log (level: LogLevel, ...fields: (string | object)[]): LogMessage {
|
||||
const msg = this.buildLogMessage(level, ...fields)
|
||||
|
||||
if (this.opts.local !== false && level >= this.opts.local) {
|
||||
this.getLocalLogFunc(msg.level)(msg.time, msg.msg, msg)
|
||||
}
|
||||
|
||||
if (this.opts.remote !== false && level >= this.opts.remote) {
|
||||
if (this.storage.get(SETTINGS).logOptin) {
|
||||
// fire & forget, no async handling as logging should not have impact on application flow
|
||||
this.http.post(this.opts.endpoint, msg, { responseType: 'text' })
|
||||
.toPromise()
|
||||
.catch(console.error)
|
||||
}
|
||||
}
|
||||
|
||||
return msg
|
||||
}
|
||||
|
||||
private buildLogMessage (level: LogLevel, ...fields: (string | object)[]): LogMessage {
|
||||
const logentry = { } as LogMessage
|
||||
let msg = ''
|
||||
|
||||
for (const param of fields) {
|
||||
if (typeof param === 'object')
|
||||
Object.assign(logentry, param)
|
||||
else
|
||||
msg = msg ? `${msg} ${param}` : param
|
||||
}
|
||||
|
||||
if (msg)
|
||||
logentry.msg = msg
|
||||
|
||||
Object.assign(logentry, this.defaultFields, {
|
||||
time: Date.now(),
|
||||
level,
|
||||
})
|
||||
|
||||
return logentry
|
||||
}
|
||||
|
||||
private getLocalLogFunc (level: LogLevel): (...params: any[]) => any {
|
||||
switch (level) {
|
||||
case LogLevel.DEBUG:
|
||||
case LogLevel.INFO:
|
||||
return console.log
|
||||
|
||||
case LogLevel.WARN:
|
||||
return console.warn
|
||||
|
||||
case LogLevel.ERROR:
|
||||
default:
|
||||
return console.error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface LogMessage {
|
||||
level: LogLevel,
|
||||
time: Date,
|
||||
app: string,
|
||||
appVersion: string,
|
||||
platform: string,
|
||||
platformVersion: string,
|
||||
|
||||
component?: string,
|
||||
msg?: string,
|
||||
[k: string]: any,
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
'use strict';
|
||||
|
||||
const http = require('http')
|
||||
const fs = require('fs')
|
||||
|
||||
const port = process.argv[2] || 4444
|
||||
const logfile = process.argv[3] || '/tmp/logs.json'
|
||||
|
||||
const resHeaders = {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Headers': 'content-type',
|
||||
'Content-Type': 'text/plain',
|
||||
}
|
||||
|
||||
const handleLog = (req, res) => {
|
||||
let body = ''
|
||||
req.on('data', chunk => {
|
||||
body += chunk.toString()
|
||||
})
|
||||
|
||||
req.on('end', () => {
|
||||
try {
|
||||
const msg = JSON.parse(body)
|
||||
msg.logclient = {
|
||||
ip: req.connection.remoteAddress,
|
||||
ua: req.headers['user-agent']
|
||||
}
|
||||
fileStream.write(JSON.stringify(msg))
|
||||
fileStream.write('\n')
|
||||
|
||||
res.writeHead(200, 'ok', resHeaders)
|
||||
res.end('ok')
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
res.writeHead(400)
|
||||
res.end('invalid payload')
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const requestHandler = (req, res) => {
|
||||
console.log(req.method, req.url)
|
||||
switch(req.method) {
|
||||
case 'OPTIONS':
|
||||
res.writeHead(200, 'ok', resHeaders)
|
||||
return res.end('ok')
|
||||
case 'POST':
|
||||
if (req.url === '/log') return handleLog(req, res)
|
||||
default:
|
||||
res.writeHead(404)
|
||||
return res.end('not found')
|
||||
}
|
||||
}
|
||||
|
||||
const fileStream = fs.createWriteStream(logfile, 'utf-8')
|
||||
const server = http.createServer(requestHandler)
|
||||
|
||||
server.listen(port, err => {
|
||||
if (err) {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
}
|
||||
console.log('listening on', port)
|
||||
console.log('writing to', logfile)
|
||||
})
|
Loading…
Reference in New Issue