Skip to content

Commit bfd8456

Browse files
Merge pull request #122 from thiagobustamante/master
log proxy time / support load middlewares installed globally
2 parents 8b1749f + 4cfb926 commit bfd8456

File tree

6 files changed

+83
-9
lines changed

6 files changed

+83
-9
lines changed

README.md

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ It provides:
3232
- **Integrated CircuitBreaker** - A fast [circuitbreaker](https://martinfowler.com/bliki/CircuitBreaker.html) to fast fail your responses when your API is having problems to work. It support custom handlers for events like "open" or "close" circuit.
3333
- Real Time **Monitoring and Analytics** -
3434
- Collect statistics about any access to your APIs. Capture any event, like a cache hit on a cache entrance, a circuitbreaker open circuit or an authentication attempt.
35-
- A very flexible and powerfull log system, that can be integrated with any service like logstash, loggly or new relic.
35+
- A very flexible and powerfull log system, that can be integrated with any service like logstash, timescale, loggly or new relic.
3636
- **Easy Administration** - The gateway can be configured remotelly. And no restart is needed. Any API configuration can be "hot" changed and all configurations are propagated to other tree-gateway cluster nodes with no pain. The gateway can be configured through:
3737
- Admin API - A REST API that can be invoked through HTTP;
3838
- SDK - A Node JS SDK that can be used to configure the Gateway (or a cluster of gateways) programmatically;
@@ -49,16 +49,47 @@ It provides:
4949
<a href="https://www.youtube.com/watch?v=FkAeEmt2wro"><img src="https://img.youtube.com/vi/FkAeEmt2wro/1.jpg"/></a>
5050

5151

52-
## Try Tree Gateway
52+
## Quick Start
53+
54+
Install the gateway:
55+
56+
```sh
57+
npm install -g tree-gateway
58+
```
59+
60+
Run it:
61+
62+
```sh
63+
treeGateway
64+
```
65+
66+
Then map your first API. Just create an YML file (my-api.yaml):
67+
68+
```yaml
69+
---
70+
name: Test
71+
version: 1.0.0
72+
path: "/test"
73+
proxy:
74+
target:
75+
host: http://httpbin.org
76+
timeout: five seconds
77+
```
78+
79+
And use the Tree Gateway CLI to configure it into the gateway:
80+
81+
```sh
82+
treeGatewayConfig apis --add ./my-api.yaml
83+
```
84+
85+
And its done. You can test it accessing in your browser: `http://localhost:8000/test/get`
86+
87+
88+
## Gateway Configuration Reference
5389

5490
Take a better look into Tree Gateway by checking out the project and working with it guided by our [Docs](https://github.com/Leanty/tree-gateway/wiki).
5591

56-
## Check out the Dashboard!
5792

58-
<p align="center">
59-
<a href="http://dashboard.leanty.com/"><img src="http://treegateway.org/img/slide/example-slide-1.png" /><a/>
60-
</p>
61-
6293
## Migrating from previous versions
6394

6495
Check our [migration guide](https://github.com/Leanty/tree-gateway/wiki/migrationGuide).

src/pipeline/proxy/proxy.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { MiddlewareLoader } from '../../utils/middleware-loader';
1313
import { ServiceDiscovery } from '../servicediscovery/service-discovery';
1414
import { WritableStreamBuffer } from 'stream-buffers';
1515
import { ApiPipelineConfig } from '../../config/gateway';
16+
import { RequestLogger } from '../stats/request';
1617
const agentKeepAlive = require('agentkeepalive');
1718
const httpProxy = require('../../../lib/http-proxy');
1819

@@ -26,6 +27,7 @@ export class ApiProxy {
2627
@Inject private logger: Logger;
2728
@Inject private middlewareLoader: MiddlewareLoader;
2829
@Inject private serviceDiscovery: ServiceDiscovery;
30+
@Inject private requestLogger: RequestLogger;
2931

3032
/**
3133
* Configure a proxy for a given API
@@ -103,7 +105,12 @@ export class ApiProxy {
103105
}
104106

105107
const proxy = httpProxy.createProxyServer(proxyConfig);
108+
const requestLogEnabled = this.requestLogger.isRequestLogEnabled(api);
106109
proxy.on('error', (err: any, req: express.Request, res: express.Response) => {
110+
if (requestLogEnabled) {
111+
const requestLog = this.requestLogger.getRequestLog(req);
112+
requestLog.proxyTime -= new Date().getTime();
113+
}
107114
const hostname = (req.headers && req.headers.host) || (req.hostname || req.host); // (websocket) || (node0.10 || node 4/5)
108115
const target = apiProxy.target.host;
109116
const errReference = 'https://nodejs.org/api/errors.html#errors_common_system_errors'; // link to Node Common Systems Errors page
@@ -113,6 +120,12 @@ export class ApiProxy {
113120
res.status(502).send('Bad Gateway');
114121
}
115122
});
123+
if (requestLogEnabled) {
124+
proxy.on('start', (req: express.Request, res: express.Response) => {
125+
const requestLog = this.requestLogger.getRequestLog(req);
126+
requestLog.proxyTime = new Date().getTime();
127+
});
128+
}
116129

117130
const maybeWrapResponse = this.interceptor.hasResponseInterceptor(api);
118131
const responseInterceptor: ResponseInterceptors = this.interceptor.buildResponseInterceptors(api, pipelineConfig);
@@ -147,7 +160,12 @@ export class ApiProxy {
147160
}
148161

149162
private handleResponseInterceptor(api: ApiConfig, proxy: any, responseInterceptor: ResponseInterceptors) {
163+
const requestLogEnabled = this.requestLogger.isRequestLogEnabled(api);
150164
proxy.on('end', (req: any, res: any, proxyRes: any, ) => {
165+
if (requestLogEnabled) {
166+
const requestLog = this.requestLogger.getRequestLog(req);
167+
requestLog.proxyTime -= new Date().getTime();
168+
}
151169
if (res.__data) {
152170
if (responseInterceptor) {
153171
responseInterceptor.middelware(res.__data.getContents(), proxyRes, req, res, res.__ignore,

src/pipeline/stats/request.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export interface RequestLog {
1818
ip: string;
1919
method: string;
2020
path: string;
21+
proxyTime: number;
2122
responseTime: number;
2223
status: number;
2324
timestamp: number;

src/utils/middleware-loader.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,12 @@ export class MiddlewareLoader {
6464
p = path.join(this.config.middlewarePath, type, middlewareId);
6565
}
6666

67-
let middleware = require(p);
67+
let middleware;
68+
try {
69+
middleware = require(p);
70+
} catch(e) {
71+
middleware = require(middlewareId);
72+
}
6873
if (middleware.factory) {
6974
middleware = middleware(middlewareConfig.options || {});
7075
}

src/utils/time-intervals.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,25 @@
33
import * as _ from 'lodash';
44
const humanInterval = require('human-interval');
55

6+
humanInterval.languageMap['eleven'] = 11;
7+
humanInterval.languageMap['twelve'] = 12;
8+
humanInterval.languageMap['thirteen'] = 13;
9+
humanInterval.languageMap['fourteen'] = 14;
10+
humanInterval.languageMap['fifteen'] = 15;
11+
humanInterval.languageMap['sixteen'] = 16;
12+
humanInterval.languageMap['seventeen'] = 17;
13+
humanInterval.languageMap['eighteen'] = 18;
14+
humanInterval.languageMap['nineteen'] = 19;
15+
humanInterval.languageMap['twenty'] = 20;
16+
humanInterval.languageMap['thirty'] = 30;
17+
humanInterval.languageMap['fourty'] = 40;
18+
humanInterval.languageMap['fifty'] = 50;
19+
humanInterval.languageMap['sixty'] = 60;
20+
humanInterval.languageMap['seventy'] = 70;
21+
humanInterval.languageMap['eighty'] = 80;
22+
humanInterval.languageMap['ninety'] = 90;
23+
humanInterval.languageMap['hundred'] = 100;
24+
625
export function getMilisecondsInterval(value: string | number | undefined, defaultValue?: number) {
726
if (!value) {
827
return defaultValue;

test/data/apis/authenticated.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"target": {
77
"host": "http://httpbin.org"
88
},
9-
"timeout": "five seconds"
9+
"timeout": "fifteen seconds"
1010
},
1111
"parseCookies": true,
1212
"authentication": {

0 commit comments

Comments
 (0)