[server] Introduce DebugApp with /debug/logging

This commit is contained in:
Gero Posmyk-Leinemann 2021-09-14 13:08:24 +00:00 committed by Robo Quat
parent 15fcc0ee42
commit 67d0ed7ad9
4 changed files with 94 additions and 8 deletions

View File

@ -326,9 +326,12 @@ components:
metrics: metrics:
expose: true expose: true
containerPort: 9500 containerPort: 9500
debug: debugNode:
expose: false expose: false
containerPort: 9229 containerPort: 9229
debug:
expose: false
containerPort: 6060
serviceSessionAffinity: None serviceSessionAffinity: None
serverContainer: serverContainer:
volumeMounts: null volumeMounts: null

View File

@ -83,6 +83,7 @@ import { defaultGRPCOptions } from '@gitpod/gitpod-protocol/lib/util/grpc';
import { IDEConfigService } from './ide-config'; import { IDEConfigService } from './ide-config';
import { PrometheusClientCallMetrics } from "@gitpod/gitpod-protocol/lib/messaging/client-call-metrics"; import { PrometheusClientCallMetrics } from "@gitpod/gitpod-protocol/lib/messaging/client-call-metrics";
import { IClientCallMetrics } from '@gitpod/content-service/lib/client-call-metrics'; import { IClientCallMetrics } from '@gitpod/content-service/lib/client-call-metrics';
import { DebugApp } from './debug-app';
export const productionContainerModule = new ContainerModule((bind, unbind, isBound, rebind) => { export const productionContainerModule = new ContainerModule((bind, unbind, isBound, rebind) => {
bind(Config).toConstantValue(ConfigFile.fromFile()); bind(Config).toConstantValue(ConfigFile.fromFile());
@ -103,6 +104,7 @@ export const productionContainerModule = new ContainerModule((bind, unbind, isBo
bind(SessionHandlerProvider).toSelf().inSingletonScope(); bind(SessionHandlerProvider).toSelf().inSingletonScope();
bind(Server).toSelf().inSingletonScope(); bind(Server).toSelf().inSingletonScope();
bind(DebugApp).toSelf().inSingletonScope();
bind(GitpodFileParser).toSelf().inSingletonScope(); bind(GitpodFileParser).toSelf().inSingletonScope();

View File

@ -0,0 +1,76 @@
/**
* Copyright (c) 2021 Gitpod GmbH. All rights reserved.
* Licensed under the GNU Affero General Public License (AGPL).
* See License-AGPL.txt in the project root for license information.
*/
import * as http from 'http';
import * as express from 'express';
import { injectable, postConstruct } from "inversify";
import { log, LogrusLogLevel } from '@gitpod/gitpod-protocol/lib/util/logging';
export interface SetLogLevelRequest {
level: LogrusLogLevel,
}
export namespace SetLogLevelRequest {
export function is(o: any): o is SetLogLevelRequest {
return typeof o === 'object'
&& 'level' in o;
}
}
@injectable()
export class DebugApp {
protected _app: express.Application;
protected httpServer: http.Server | undefined = undefined;
@postConstruct()
public ctor() {
this._app = this.create();
}
create(): express.Application {
const app = express();
app.post('/debug/logging', (req, res) => {
try {
const parsed = JSON.parse(req.body);
if (!SetLogLevelRequest.is(parsed)) {
res.status(400).end("not a SetLogLevelRequest");
return;
}
const newLogLevel = parsed.level;
log.setLogLevel(newLogLevel);
log.info("set log level", { newLogLevel });
} catch (err) {
res.status(500).end(err);
}
});
return app;
}
public start(port: number) {
this.httpServer = this._app.listen(port, 'localhost', () => {
log.info(`debug server listening on port: ${port}`);
});
}
public async stop() {
const server = this.httpServer;
if (!server) {
return;
}
return new Promise<void>((resolve) => server.close((err: any) => {
if (err) {
log.warn(`error while closing http server`, { err });
}
this.httpServer = undefined;
resolve();
}));
}
public get app(): express.Application {
return this._app;
}
}

View File

@ -41,6 +41,7 @@ import { OAuthController } from './oauth-server/oauth-controller';
import { HeadlessLogController, HEADLESS_LOGS_PATH_PREFIX, HEADLESS_LOG_DOWNLOAD_PATH_PREFIX } from './workspace/headless-log-controller'; import { HeadlessLogController, HEADLESS_LOGS_PATH_PREFIX, HEADLESS_LOG_DOWNLOAD_PATH_PREFIX } from './workspace/headless-log-controller';
import { NewsletterSubscriptionController } from './user/newsletter-subscription-controller'; import { NewsletterSubscriptionController } from './user/newsletter-subscription-controller';
import { Config } from './config'; import { Config } from './config';
import { DebugApp } from './debug-app';
@injectable() @injectable()
export class Server<C extends GitpodClient, S extends GitpodServer> { export class Server<C extends GitpodClient, S extends GitpodServer> {
@ -58,6 +59,7 @@ export class Server<C extends GitpodClient, S extends GitpodServer> {
@inject(MonitoringEndpointsApp) protected readonly monitoringEndpointsApp: MonitoringEndpointsApp; @inject(MonitoringEndpointsApp) protected readonly monitoringEndpointsApp: MonitoringEndpointsApp;
@inject(CodeSyncService) private readonly codeSyncService: CodeSyncService; @inject(CodeSyncService) private readonly codeSyncService: CodeSyncService;
@inject(HeadlessLogController) protected readonly headlessLogController: HeadlessLogController; @inject(HeadlessLogController) protected readonly headlessLogController: HeadlessLogController;
@inject(DebugApp) protected readonly debugApp: DebugApp;
@inject(RabbitMQConsensusLeaderMessenger) protected readonly consensusMessenger: RabbitMQConsensusLeaderMessenger; @inject(RabbitMQConsensusLeaderMessenger) protected readonly consensusMessenger: RabbitMQConsensusLeaderMessenger;
@inject(ConsensusLeaderQorum) protected readonly qorum: ConsensusLeaderQorum; @inject(ConsensusLeaderQorum) protected readonly qorum: ConsensusLeaderQorum;
@ -76,8 +78,8 @@ export class Server<C extends GitpodClient, S extends GitpodServer> {
protected readonly eventEmitter = new EventEmitter(); protected readonly eventEmitter = new EventEmitter();
protected app?: express.Application; protected app?: express.Application;
protected httpServer?: http.Server; protected httpServer?: http.Server;
protected monApp?: express.Application; protected monitoringApp?: express.Application;
protected monHttpServer?: http.Server; protected monitoringHttpServer?: http.Server;
public async init(app: express.Application) { public async init(app: express.Application) {
log.setVersion(this.config.version); log.setVersion(this.config.version);
@ -210,7 +212,7 @@ export class Server<C extends GitpodClient, S extends GitpodServer> {
// Health check + metrics endpoints // Health check + metrics endpoints
this.monApp = this.monitoringEndpointsApp.create(); this.monitoringApp = this.monitoringEndpointsApp.create();
// Report current websocket connections // Report current websocket connections
this.installWebsocketConnectionGauge(); this.installWebsocketConnectionGauge();
@ -274,15 +276,18 @@ export class Server<C extends GitpodClient, S extends GitpodServer> {
}) })
this.httpServer = httpServer; this.httpServer = httpServer;
if (this.monApp) { if (this.monitoringApp) {
this.monHttpServer = this.monApp.listen(9500, 'localhost', () => { this.monitoringHttpServer = this.monitoringApp.listen(9500, 'localhost', () => {
log.info(`monitoring app listening on port: ${(<AddressInfo>this.monHttpServer!.address()).port}`); log.info(`monitoring app listening on port: ${(<AddressInfo>this.monitoringHttpServer!.address()).port}`);
}); });
} }
this.debugApp.start(6060);
} }
public async stop() { public async stop() {
await this.stopServer(this.monHttpServer); await this.debugApp.stop();
await this.stopServer(this.monitoringHttpServer);
await this.stopServer(this.httpServer); await this.stopServer(this.httpServer);
log.info('server stopped.'); log.info('server stopped.');
} }