Skip to content

Commit

Permalink
Plugin: Migrate to @grpc/grpc-js to resolve problems when IPv6 is dis…
Browse files Browse the repository at this point in the history
…abled (grafana#135)

* Migrate to @grpc/grpc-js
* Download grpc no longer needed as part of packaging
* Package using node 12 (^8.13.0 || >=10.10.0) required for grpc-js
* zeit/pkg upgrade to support node 12
Signed-off-by: Arve Knudsen <[email protected]>

Co-authored-by: Marcus Efraimsson <[email protected]>
  • Loading branch information
aknuds1 and marefr authored May 13, 2020
1 parent d70d1dc commit 3ad1228
Show file tree
Hide file tree
Showing 10 changed files with 266 additions and 1,368 deletions.
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
"start": "node build/app.js --config=dev.json"
},
"dependencies": {
"@grpc/proto-loader": "^0.5.3",
"@grpc/grpc-js": "^1.0",
"@grpc/proto-loader": "^0.5.4",
"@hapi/boom": "^8.0.1",
"express": "^4.16.3",
"express-prom-bundle": "^5.1.5",
"google-protobuf": "3.5.0",
"grpc": "^1.24.2",
"lodash": "^4.17.15",
"minimist": "^1.2.0",
"morgan": "^1.9.0",
Expand All @@ -39,7 +39,7 @@
"@types/node": "^10.0.9",
"husky": "^3.1.0",
"lint-staged": "^9.5.0",
"pkg": "4.3.8",
"pkg": "4.4.8",
"prettier": "^1.19.1",
"tsc-watch": "^4.2.3",
"tslint": "^6.1.1",
Expand All @@ -65,5 +65,8 @@
"bin": "build/app.js",
"engines": {
"node": ">=12 <13"
},
"volta": {
"node": "12.16.2"
}
}
79 changes: 0 additions & 79 deletions scripts/download_grpc.js

This file was deleted.

6 changes: 0 additions & 6 deletions scripts/package_target.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,6 @@ if [ $? != 0 ]; then
echo "${?}\n". 1>&2 && exit 1
fi

node scripts/download_grpc.js ${ARCH} ${OUT}

if [ $? != 0 ]; then
echo "${?}\n". 1>&2 && exit 1
fi

node scripts/rename_executable.js ${ARCH} ${OUT}

if [ $? != 0 ]; then
Expand Down
2 changes: 1 addition & 1 deletion scripts/pkg.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ platform = platformTransform[platform] || platform;
arch = archTransform[arch] || arch;
const outputPath = "dist/" + (process.argv[3] || `plugin-${archArg}`);

childProcess.execSync(`./node_modules/.bin/pkg -t node10-${platform}-${arch} . --out-path ${outputPath}`, {stdio: 'inherit'});
childProcess.execSync(`./node_modules/.bin/pkg -t node12-${platform}-${arch} . --out-path ${outputPath}`, {stdio: 'inherit'});
2 changes: 1 addition & 1 deletion src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ async function main() {
config.rendering.chromeBin = [path.dirname(process.execPath), ...parts].join(path.sep);
}

serve({
await serve({
handshakeConfig: {
protocolVersion: 2,
magicCookieKey: 'grafana_plugin_type',
Expand Down
27 changes: 17 additions & 10 deletions src/node-plugin/lib/server.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as grpc from 'grpc';
import * as grpc from '@grpc/grpc-js';
import * as protoLoader from '@grpc/proto-loader';
import { coreProtocolVersion, PluginSet, VersionedPluginSet, ServeConfig } from './types';
import { PluginLogger } from '../../logger';
Expand Down Expand Up @@ -81,7 +81,7 @@ const protocolVersion = (opts: ServeConfig): ProtocolNegotiation => {
};
};

export const serve = (opts: ServeConfig) => {
export const serve = async (opts: ServeConfig) => {
const env = Object.assign({}, process.env);
opts.logger = opts.logger || new PluginLogger();

Expand Down Expand Up @@ -113,19 +113,26 @@ export const serve = (opts: ServeConfig) => {
for (const key in pluginSet) {
if (pluginSet.hasOwnProperty(key)) {
const p = pluginSet[key];
p.grpcServer(server);
await p.grpcServer(server);
}
}

opts.grpcHost = opts.grpcHost || '127.0.0.1';
opts.grpcPort = opts.grpcPort || 0;

const address = `${opts.grpcHost}:${opts.grpcPort}`;
const boundPortNumber = server.bind(address, grpc.ServerCredentials.createInsecure());
if (boundPortNumber === 0) {
throw new Error(`failed to bind address=${address}, boundPortNumber=${boundPortNumber}`);
}
return new Promise<void>((resolve, reject) => {
const address = `${opts.grpcHost}:${opts.grpcPort}`;
server.bindAsync(address, grpc.ServerCredentials.createInsecure(), (error: Error | null, port: number) => {
if (error) {
reject(error);
}
if (port === 0) {
reject(new Error(`failed to bind address=${address}, boundPortNumber=${port}`));
}

server.start();
console.log(`${coreProtocolVersion}|${protoVersion}|tcp|${opts.grpcHost}:${boundPortNumber}|grpc`);
server.start();
console.log(`${coreProtocolVersion}|${protoVersion}|tcp|${opts.grpcHost}:${port}|grpc`);
resolve();
});
});
};
2 changes: 1 addition & 1 deletion src/node-plugin/lib/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as grpc from 'grpc';
import * as grpc from '@grpc/grpc-js';
import { Logger } from '../../logger';

export interface GrpcPlugin {
Expand Down
70 changes: 30 additions & 40 deletions src/plugin/v1/grpc_plugin.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as grpc from 'grpc';
import * as grpc from '@grpc/grpc-js';
import * as protoLoader from '@grpc/proto-loader';
import { GrpcPlugin } from '../../node-plugin';
import { Logger } from '../../logger';
Expand All @@ -21,44 +21,34 @@ export class RenderGRPCPluginV1 implements GrpcPlugin {

async grpcServer(server: grpc.Server) {
const serviceDef = rendererProtoDescriptor['models']['Renderer']['service'];
const service = new RendererGRPCServer(this.config, this.log);
server.addService(serviceDef, service);
service.start();
}
}

class RendererGRPCServer {
private browser: Browser;

constructor(config: PluginConfig, private log: Logger) {
this.browser = createBrowser(config.rendering, log);
}

async start() {
await this.browser.start();
}

async render(call, callback) {
const req = call.request;
const options: RenderOptions = {
url: req.url,
width: req.width,
height: req.height,
filePath: req.filePath,
timeout: req.timeout,
renderKey: req.renderKey,
domain: req.domain,
timezone: req.timezone,
encoding: req.encoding,
};

try {
this.log.debug('Render request received', 'url', options.url);
await this.browser.render(options);
callback(null, { error: '' });
} catch (err) {
this.log.error('Render request failed', 'url', options.url, 'error', err.toString());
callback(null, { error: err.toString() });
}
const browser = createBrowser(this.config.rendering, this.log);
server.addService(serviceDef, {
render: (call: grpc.ServerUnaryCall<any, any>, callback) => {
const req = call.request;
const options: RenderOptions = {
url: req.url,
width: req.width,
height: req.height,
filePath: req.filePath,
timeout: req.timeout,
renderKey: req.renderKey,
domain: req.domain,
timezone: req.timezone,
encoding: req.encoding,
};

this.log.debug('Render request received', 'url', options.url);
browser.render(options).then(
() => {
callback(null, { error: '' });
},
err => {
this.log.error('Render request failed', 'url', options.url, 'error', err.toString());
callback(null, { error: err.toString() });
}
);
},
});
await browser.start();
}
}
16 changes: 10 additions & 6 deletions src/plugin/v2/grpc_plugin.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as grpc from 'grpc';
import * as grpc from '@grpc/grpc-js';
import * as protoLoader from '@grpc/proto-loader';
import * as promClient from 'prom-client';
import { GrpcPlugin } from '../../node-plugin';
Expand Down Expand Up @@ -45,10 +45,10 @@ export class RenderGRPCPluginV2 implements GrpcPlugin {
const pluginService = new PluginGRPCServer(browser, this.log);

const rendererServiceDef = rendererV2ProtoDescriptor['pluginextensionv2']['Renderer']['service'];
server.addService(rendererServiceDef, pluginService);
server.addService(rendererServiceDef, pluginService as any);

const pluginServiceDef = pluginV2ProtoDescriptor['pluginv2']['Diagnostics']['service'];
server.addService(pluginServiceDef, pluginService);
server.addService(pluginServiceDef, pluginService as any);

const metrics = setupMetrics();
metrics.up.set(1);
Expand Down Expand Up @@ -81,10 +81,14 @@ class PluginGRPCServer {
await this.browser.start();
}

async render(call: grpc.ServerUnaryCall<RenderRequest>, callback: grpc.sendUnaryData<RenderResponse>) {
async render(call: grpc.ServerUnaryCall<RenderRequest, any>, callback: grpc.sendUnaryData<RenderResponse>) {
const req = call.request;
const headers: HTTPHeaders = {};

if (!req) {
throw new Error('Request cannot be null');
}

if (req.headers) {
for (const key in req.headers) {
if (req.headers.hasOwnProperty(key)) {
Expand Down Expand Up @@ -118,7 +122,7 @@ class PluginGRPCServer {
callback(null, { error: errStr });
}

async checkHealth(_: grpc.ServerUnaryCall<CheckHealthRequest>, callback: grpc.sendUnaryData<CheckHealthResponse>) {
async checkHealth(_: grpc.ServerUnaryCall<CheckHealthRequest, any>, callback: grpc.sendUnaryData<CheckHealthResponse>) {
const jsonDetails = Buffer.from(
JSON.stringify({
browserVersion: this.browserVersion,
Expand All @@ -128,7 +132,7 @@ class PluginGRPCServer {
callback(null, { status: HealthStatus.OK, message: 'Success', jsonDetails: jsonDetails });
}

async collectMetrics(_: grpc.ServerUnaryCall<CollectMetricsRequest>, callback: grpc.sendUnaryData<CollectMetricsResponse>) {
async collectMetrics(_: grpc.ServerUnaryCall<CollectMetricsRequest, any>, callback: grpc.sendUnaryData<CollectMetricsResponse>) {
const payload = Buffer.from(promClient.register.metrics());
callback(null, { metrics: { prometheus: payload } });
}
Expand Down
Loading

0 comments on commit 3ad1228

Please sign in to comment.