Adding stats, code, timings and size of request.
This commit is contained in:
parent
5936fe0f5f
commit
99e2cd52e8
|
@ -109,7 +109,7 @@ exports.preview = async function (ctx) {
|
|||
const enrichedQuery = await enrichQueryFields(fields, parameters)
|
||||
|
||||
try {
|
||||
const { rows, keys } = await Runner.run({
|
||||
const { rows, keys, info } = await Runner.run({
|
||||
datasource,
|
||||
queryVerb,
|
||||
query: enrichedQuery,
|
||||
|
@ -119,6 +119,7 @@ exports.preview = async function (ctx) {
|
|||
ctx.body = {
|
||||
rows,
|
||||
schemaFields: [...new Set(keys)],
|
||||
info,
|
||||
}
|
||||
} catch (err) {
|
||||
ctx.throw(400, err)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
export interface IntegrationBase {
|
||||
create?(query: any): Promise<any[]>
|
||||
read?(query: any): Promise<any[]>
|
||||
update?(query: any): Promise<any[]>
|
||||
delete?(query: any): Promise<any[]>
|
||||
create?(query: any): Promise<any[]|any>
|
||||
read?(query: any): Promise<any[]|any>
|
||||
update?(query: any): Promise<any[]|any>
|
||||
delete?(query: any): Promise<any[]|any>
|
||||
}
|
||||
|
|
|
@ -38,6 +38,8 @@ const coreFields = {
|
|||
|
||||
module RestModule {
|
||||
const fetch = require("node-fetch")
|
||||
const { formatBytes } = require("../utilities")
|
||||
const { performance } = require("perf_hooks")
|
||||
|
||||
interface RestConfig {
|
||||
url: string
|
||||
|
@ -46,6 +48,13 @@ module RestModule {
|
|||
}
|
||||
}
|
||||
|
||||
interface Request {
|
||||
path: string
|
||||
queryString?: string
|
||||
headers?: string
|
||||
json?: any
|
||||
}
|
||||
|
||||
const SCHEMA: Integration = {
|
||||
docs: "https://github.com/node-fetch/node-fetch",
|
||||
description:
|
||||
|
@ -102,17 +111,29 @@ module RestModule {
|
|||
private headers: {
|
||||
[key: string]: string
|
||||
} = {}
|
||||
private startTimeMs: number = performance.now()
|
||||
|
||||
constructor(config: RestConfig) {
|
||||
this.config = config
|
||||
}
|
||||
|
||||
async parseResponse(response: any) {
|
||||
let data
|
||||
const contentType = response.headers.get("content-type")
|
||||
if (contentType && contentType.indexOf("application/json") !== -1) {
|
||||
return await response.json()
|
||||
data = await response.json()
|
||||
} else {
|
||||
return await response.text()
|
||||
data = await response.text()
|
||||
}
|
||||
const size = formatBytes(response.headers.get("content-length") || 0)
|
||||
const time = `${Math.round(performance.now() - this.startTimeMs)}ms`
|
||||
return {
|
||||
data,
|
||||
info: {
|
||||
code: response.status,
|
||||
size,
|
||||
time,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,76 +146,40 @@ module RestModule {
|
|||
}
|
||||
}
|
||||
|
||||
async create({ path = "", queryString = "", headers = {}, json = {} }) {
|
||||
async _req({ path = "", queryString = "", headers = {}, json = {}, method = "GET" }) {
|
||||
this.headers = {
|
||||
...this.config.defaultHeaders,
|
||||
...headers,
|
||||
}
|
||||
|
||||
const response = await fetch(this.getUrl(path, queryString), {
|
||||
method: "POST",
|
||||
headers: this.headers,
|
||||
body: JSON.stringify(json),
|
||||
})
|
||||
const input: any = { method, headers: this.headers }
|
||||
if (json && typeof json === "object" && Object.keys(json).length > 0) {
|
||||
input.body = JSON.stringify(json)
|
||||
}
|
||||
|
||||
this.startTimeMs = performance.now()
|
||||
const response = await fetch(this.getUrl(path, queryString), input)
|
||||
return await this.parseResponse(response)
|
||||
}
|
||||
|
||||
async read({ path = "", queryString = "", headers = {} }) {
|
||||
this.headers = {
|
||||
...this.config.defaultHeaders,
|
||||
...headers,
|
||||
}
|
||||
|
||||
const response = await fetch(this.getUrl(path, queryString), {
|
||||
headers: this.headers,
|
||||
})
|
||||
|
||||
return await this.parseResponse(response)
|
||||
async create(opts: Request) {
|
||||
return this._req({ ...opts, method: "POST" })
|
||||
}
|
||||
|
||||
async update({ path = "", queryString = "", headers = {}, json = {} }) {
|
||||
this.headers = {
|
||||
...this.config.defaultHeaders,
|
||||
...headers,
|
||||
}
|
||||
|
||||
const response = await fetch(this.getUrl(path, queryString), {
|
||||
method: "PUT",
|
||||
headers: this.headers,
|
||||
body: JSON.stringify(json),
|
||||
})
|
||||
|
||||
return await this.parseResponse(response)
|
||||
async read(opts: Request) {
|
||||
return this._req({ ...opts, method: "GET" })
|
||||
}
|
||||
|
||||
async patch({ path = "", queryString = "", headers = {}, json = {} }) {
|
||||
this.headers = {
|
||||
...this.config.defaultHeaders,
|
||||
...headers,
|
||||
}
|
||||
|
||||
const response = await fetch(this.getUrl(path, queryString), {
|
||||
method: "PATCH",
|
||||
headers: this.headers,
|
||||
body: JSON.stringify(json),
|
||||
})
|
||||
|
||||
return await this.parseResponse(response)
|
||||
async update(opts: Request) {
|
||||
return this._req({ ...opts, method: "PUT" })
|
||||
}
|
||||
|
||||
async delete({ path = "", queryString = "", headers = {} }) {
|
||||
this.headers = {
|
||||
...this.config.defaultHeaders,
|
||||
...headers,
|
||||
}
|
||||
async patch(opts: Request) {
|
||||
return this._req({ ...opts, method: "PATCH" })
|
||||
}
|
||||
|
||||
const response = await fetch(this.getUrl(path, queryString), {
|
||||
method: "DELETE",
|
||||
headers: this.headers,
|
||||
})
|
||||
|
||||
return await this.parseResponse(response)
|
||||
async delete(opts: Request) {
|
||||
return this._req({ ...opts, method: "DELETE" })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,15 @@ function formatResponse(resp) {
|
|||
return resp
|
||||
}
|
||||
|
||||
function hasExtraData(response) {
|
||||
return (
|
||||
typeof response === "object" &&
|
||||
!Array.isArray(response) &&
|
||||
response.data &&
|
||||
response.info
|
||||
)
|
||||
}
|
||||
|
||||
async function runAndTransform(datasource, queryVerb, query, transformer) {
|
||||
const Integration = integrations[datasource.source]
|
||||
if (!Integration) {
|
||||
|
@ -22,7 +31,13 @@ async function runAndTransform(datasource, queryVerb, query, transformer) {
|
|||
}
|
||||
const integration = new Integration(datasource.config)
|
||||
|
||||
let rows = formatResponse(await integration[queryVerb](query))
|
||||
let output = formatResponse(await integration[queryVerb](query))
|
||||
let rows = output,
|
||||
info = undefined
|
||||
if (hasExtraData(output)) {
|
||||
rows = output.data
|
||||
info = output.info
|
||||
}
|
||||
|
||||
// transform as required
|
||||
if (transformer) {
|
||||
|
@ -47,7 +62,7 @@ async function runAndTransform(datasource, queryVerb, query, transformer) {
|
|||
integration.end()
|
||||
}
|
||||
|
||||
return { rows, keys }
|
||||
return { rows, keys, info }
|
||||
}
|
||||
|
||||
module.exports = (input, callback) => {
|
||||
|
|
|
@ -150,3 +150,14 @@ exports.doesDatabaseExist = async dbName => {
|
|||
return false
|
||||
}
|
||||
}
|
||||
|
||||
exports.formatBytes = bytes => {
|
||||
const units = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
|
||||
const byteIncrements = 1024
|
||||
let unit = 0
|
||||
let size = parseInt(bytes, 10) || 0
|
||||
while (size >= byteIncrements && ++unit) {
|
||||
size /= byteIncrements
|
||||
}
|
||||
return `${size.toFixed(size < 10 && unit > 0 ? 1 : 0)}${units[unit]}`
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue