Adding loggers to TS client
This commit is contained in:
parent
978f5cebc0
commit
e4c1b888ca
|
|
@ -3,6 +3,8 @@ import { IConnection } from "./IConnection"
|
|||
import { ITransport, TransferMode, TransportType, WebSocketTransport, ServerSentEventsTransport, LongPollingTransport } from "./Transports"
|
||||
import { IHttpClient, HttpClient } from "./HttpClient"
|
||||
import { IHttpConnectionOptions } from "./IHttpConnectionOptions"
|
||||
import { ILogger, LogLevel } from "./ILogger"
|
||||
import { NullLogger } from "./Loggers"
|
||||
|
||||
const enum ConnectionState {
|
||||
Initial,
|
||||
|
|
@ -19,10 +21,11 @@ interface INegotiateResponse {
|
|||
export class HttpConnection implements IConnection {
|
||||
private connectionState: ConnectionState;
|
||||
private url: string;
|
||||
private connectionId: string;
|
||||
private httpClient: IHttpClient;
|
||||
private readonly httpClient: IHttpClient;
|
||||
private readonly logger: ILogger;
|
||||
private readonly options: IHttpConnectionOptions;
|
||||
private transport: ITransport;
|
||||
private options: IHttpConnectionOptions;
|
||||
private connectionId: string;
|
||||
private startPromise: Promise<void>;
|
||||
|
||||
readonly features: any = {};
|
||||
|
|
@ -30,6 +33,7 @@ export class HttpConnection implements IConnection {
|
|||
constructor(url: string, options: IHttpConnectionOptions = {}) {
|
||||
this.url = url;
|
||||
this.httpClient = options.httpClient || new HttpClient();
|
||||
this.logger = options.logger || new NullLogger();
|
||||
this.connectionState = ConnectionState.Initial;
|
||||
this.options = options;
|
||||
}
|
||||
|
|
@ -74,7 +78,7 @@ export class HttpConnection implements IConnection {
|
|||
this.changeState(ConnectionState.Connecting, ConnectionState.Connected);
|
||||
}
|
||||
catch (e) {
|
||||
console.log("Failed to start the connection. " + e);
|
||||
this.logger.log(LogLevel.Error, "Failed to start the connection. " + e);
|
||||
this.connectionState = ConnectionState.Disconnected;
|
||||
this.transport = null;
|
||||
throw e;
|
||||
|
|
@ -86,13 +90,13 @@ export class HttpConnection implements IConnection {
|
|||
transport = TransportType[availableTransports[0]];
|
||||
}
|
||||
if (transport === TransportType.WebSockets && availableTransports.indexOf(TransportType[transport]) >= 0) {
|
||||
return new WebSocketTransport();
|
||||
return new WebSocketTransport(this.logger);
|
||||
}
|
||||
if (transport === TransportType.ServerSentEvents && availableTransports.indexOf(TransportType[transport]) >= 0) {
|
||||
return new ServerSentEventsTransport(this.httpClient);
|
||||
return new ServerSentEventsTransport(this.httpClient, this.logger);
|
||||
}
|
||||
if (transport === TransportType.LongPolling && availableTransports.indexOf(TransportType[transport]) >= 0) {
|
||||
return new LongPollingTransport(this.httpClient);
|
||||
return new LongPollingTransport(this.httpClient, this.logger);
|
||||
}
|
||||
|
||||
if (this.isITransport(transport)) {
|
||||
|
|
|
|||
|
|
@ -6,21 +6,27 @@ import { IHubProtocol, ProtocolType, MessageType, HubMessage, CompletionMessage,
|
|||
import { JsonHubProtocol } from "./JsonHubProtocol";
|
||||
import { TextMessageFormat } from "./Formatters"
|
||||
import { Base64EncodedHubProtocol } from "./Base64EncodedHubProtocol"
|
||||
import { ILogger, LogLevel } from "./ILogger"
|
||||
import { NullLogger } from "./Loggers"
|
||||
|
||||
export { TransportType } from "./Transports"
|
||||
export { HttpConnection } from "./HttpConnection"
|
||||
export { JsonHubProtocol } from "./JsonHubProtocol"
|
||||
export { LogLevel } from "./ILogger"
|
||||
export { ConsoleLogger } from "./Loggers"
|
||||
|
||||
export class HubConnection {
|
||||
private connection: IConnection;
|
||||
private readonly connection: IConnection;
|
||||
private readonly logger: ILogger;
|
||||
private protocol: IHubProtocol;
|
||||
private callbacks: Map<string, (invocationUpdate: CompletionMessage | ResultMessage) => void>;
|
||||
private methods: Map<string, (...args: any[]) => void>;
|
||||
private id: number;
|
||||
private connectionClosedCallback: ConnectionClosed;
|
||||
private protocol: IHubProtocol;
|
||||
|
||||
constructor(connection: IConnection, protocol: IHubProtocol = new JsonHubProtocol()) {
|
||||
constructor(connection: IConnection, logger: ILogger = new NullLogger(), protocol: IHubProtocol = new JsonHubProtocol()) {
|
||||
this.connection = connection;
|
||||
this.logger = logger || new NullLogger();
|
||||
this.protocol = protocol || new JsonHubProtocol();
|
||||
this.connection.onDataReceived = data => {
|
||||
this.onDataReceived(data);
|
||||
|
|
@ -57,7 +63,7 @@ export class HubConnection {
|
|||
}
|
||||
break;
|
||||
default:
|
||||
console.log("Invalid message type: " + data);
|
||||
this.logger.log(LogLevel.Warning, "Invalid message type: " + data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -72,7 +78,7 @@ export class HubConnection {
|
|||
}
|
||||
}
|
||||
else {
|
||||
console.log(`No client method with the name '${invocationMessage.target}' found.`);
|
||||
this.logger.log(LogLevel.Warning, `No client method with the name '${invocationMessage.target}' found.`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
import { IHttpClient } from "./HttpClient"
|
||||
import { TransportType, ITransport } from "./Transports"
|
||||
import { ILogger } from "./ILogger";
|
||||
|
||||
export interface IHttpConnectionOptions {
|
||||
httpClient?: IHttpClient;
|
||||
transport?: TransportType | ITransport;
|
||||
logger?: ILogger;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
export enum LogLevel {
|
||||
Information = 0,
|
||||
Warning,
|
||||
Error,
|
||||
None
|
||||
}
|
||||
|
||||
export interface ILogger {
|
||||
log(logLevel: LogLevel, message: string): void;
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
import { ILogger, LogLevel } from "./ILogger"
|
||||
|
||||
export class NullLogger implements ILogger {
|
||||
log(logLevel: LogLevel, message: string): void {
|
||||
}
|
||||
}
|
||||
|
||||
export class ConsoleLogger implements ILogger {
|
||||
private readonly minimumLogLevel: LogLevel;
|
||||
|
||||
constructor(minimumLogLevel: LogLevel) {
|
||||
this.minimumLogLevel = minimumLogLevel;
|
||||
}
|
||||
|
||||
log(logLevel: LogLevel, message: string): void {
|
||||
if (logLevel >= this.minimumLogLevel) {
|
||||
console.log(`${LogLevel[logLevel]}: ${message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import { DataReceived, TransportClosed } from "./Common"
|
||||
import { IHttpClient } from "./HttpClient"
|
||||
import { HttpError } from "./HttpError"
|
||||
import { ILogger, LogLevel } from "./ILogger"
|
||||
|
||||
export enum TransportType {
|
||||
WebSockets,
|
||||
|
|
@ -22,8 +23,13 @@ export interface ITransport {
|
|||
}
|
||||
|
||||
export class WebSocketTransport implements ITransport {
|
||||
private readonly logger: ILogger;
|
||||
private webSocket: WebSocket;
|
||||
|
||||
constructor(logger: ILogger) {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
connect(url: string, requestedTransferMode: TransferMode): Promise<TransferMode> {
|
||||
|
||||
return new Promise<TransferMode>((resolve, reject) => {
|
||||
|
|
@ -35,7 +41,7 @@ export class WebSocketTransport implements ITransport {
|
|||
}
|
||||
|
||||
webSocket.onopen = (event: Event) => {
|
||||
console.log(`WebSocket connected to ${url}`);
|
||||
this.logger.log(LogLevel.Information, `WebSocket connected to ${url}`);
|
||||
this.webSocket = webSocket;
|
||||
resolve(requestedTransferMode);
|
||||
};
|
||||
|
|
@ -45,7 +51,7 @@ export class WebSocketTransport implements ITransport {
|
|||
};
|
||||
|
||||
webSocket.onmessage = (message: MessageEvent) => {
|
||||
console.log(`(WebSockets transport) data received: ${message.data}`);
|
||||
this.logger.log(LogLevel.Information, `(WebSockets transport) data received: ${message.data}`);
|
||||
if (this.onDataReceived) {
|
||||
this.onDataReceived(message.data);
|
||||
}
|
||||
|
|
@ -86,12 +92,14 @@ export class WebSocketTransport implements ITransport {
|
|||
}
|
||||
|
||||
export class ServerSentEventsTransport implements ITransport {
|
||||
private readonly httpClient: IHttpClient;
|
||||
private readonly logger: ILogger;
|
||||
private eventSource: EventSource;
|
||||
private url: string;
|
||||
private httpClient: IHttpClient;
|
||||
|
||||
constructor(httpClient: IHttpClient) {
|
||||
constructor(httpClient: IHttpClient, logger: ILogger) {
|
||||
this.httpClient = httpClient;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
connect(url: string, requestedTransferMode: TransferMode): Promise<TransferMode> {
|
||||
|
|
@ -107,7 +115,7 @@ export class ServerSentEventsTransport implements ITransport {
|
|||
eventSource.onmessage = (e: MessageEvent) => {
|
||||
if (this.onDataReceived) {
|
||||
try {
|
||||
console.log(`(SSE transport) data received: ${e.data}`);
|
||||
this.logger.log(LogLevel.Information, `(SSE transport) data received: ${e.data}`);
|
||||
this.onDataReceived(e.data);
|
||||
} catch (error) {
|
||||
if (this.onClosed) {
|
||||
|
|
@ -128,7 +136,7 @@ export class ServerSentEventsTransport implements ITransport {
|
|||
}
|
||||
|
||||
eventSource.onopen = () => {
|
||||
console.log(`SSE connected to ${this.url}`);
|
||||
this.logger.log(LogLevel.Information, `SSE connected to ${this.url}`);
|
||||
this.eventSource = eventSource;
|
||||
// SSE is a text protocol
|
||||
resolve(TransferMode.Text);
|
||||
|
|
@ -156,13 +164,16 @@ export class ServerSentEventsTransport implements ITransport {
|
|||
}
|
||||
|
||||
export class LongPollingTransport implements ITransport {
|
||||
private readonly httpClient: IHttpClient;
|
||||
private readonly logger: ILogger;
|
||||
|
||||
private url: string;
|
||||
private httpClient: IHttpClient;
|
||||
private pollXhr: XMLHttpRequest;
|
||||
private shouldPoll: boolean;
|
||||
|
||||
constructor(httpClient: IHttpClient) {
|
||||
constructor(httpClient: IHttpClient, logger: ILogger) {
|
||||
this.httpClient = httpClient;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
connect(url: string, requestedTransferMode: TransferMode): Promise<TransferMode> {
|
||||
|
|
@ -187,11 +198,11 @@ export class LongPollingTransport implements ITransport {
|
|||
if (this.onDataReceived) {
|
||||
try {
|
||||
if (pollXhr.response) {
|
||||
console.log(`(LongPolling transport) data received: ${pollXhr.response}`);
|
||||
this.logger.log(LogLevel.Information, `(LongPolling transport) data received: ${pollXhr.response}`);
|
||||
this.onDataReceived(pollXhr.response);
|
||||
}
|
||||
else {
|
||||
console.log(`(LongPolling transport) timed out`);
|
||||
this.logger.log(LogLevel.Information, "(LongPolling transport) timed out");
|
||||
}
|
||||
} catch (error) {
|
||||
if (this.onClosed) {
|
||||
|
|
|
|||
|
|
@ -3,4 +3,5 @@ export * from "./HttpConnection"
|
|||
export * from "./HttpClient"
|
||||
export * from "./HubConnection"
|
||||
export * from "./Transports"
|
||||
export * from "./Loggers"
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,11 @@ describe('connection', () => {
|
|||
eachTransport(transportType => {
|
||||
it(`over ${signalR.TransportType[transportType]} can send and receive messages`, done => {
|
||||
const message = "Hello World!";
|
||||
let connection = new signalR.HttpConnection(ECHOENDPOINT_URL, { transport: transportType });
|
||||
let connection = new signalR.HttpConnection(ECHOENDPOINT_URL,
|
||||
{
|
||||
transport: transportType,
|
||||
logger: new signalR.ConsoleLogger(signalR.LogLevel.Information)
|
||||
});
|
||||
|
||||
let received = "";
|
||||
connection.onDataReceived = data => {
|
||||
|
|
|
|||
|
|
@ -5,8 +5,12 @@ describe('hubConnection', () => {
|
|||
describe(`${protocol.name} over ${signalR.TransportType[transportType]} transport`, () => {
|
||||
it(`can invoke server method and receive result`, done => {
|
||||
const message = "你好,世界!";
|
||||
let hubConnection = new signalR.HubConnection(
|
||||
new signalR.HttpConnection(TESTHUBENDPOINT_URL, { transport: transportType }), protocol);
|
||||
let logger = new signalR.ConsoleLogger(signalR.LogLevel.Information);
|
||||
let hubConnection = new signalR.HubConnection(new signalR.HttpConnection(
|
||||
TESTHUBENDPOINT_URL,
|
||||
{ transport: transportType, logger: logger }),
|
||||
logger,
|
||||
protocol);
|
||||
hubConnection.onClosed = error => {
|
||||
expect(error).toBe(undefined);
|
||||
done();
|
||||
|
|
@ -32,8 +36,13 @@ describe('hubConnection', () => {
|
|||
});
|
||||
|
||||
it(`can stream server method and receive result`, done => {
|
||||
let hubConnection = new signalR.HubConnection(
|
||||
new signalR.HttpConnection(TESTHUBENDPOINT_URL, { transport: transportType }), protocol);
|
||||
let logger = new signalR.ConsoleLogger(signalR.LogLevel.Information);
|
||||
let hubConnection = new signalR.HubConnection(new signalR.HttpConnection(
|
||||
TESTHUBENDPOINT_URL,
|
||||
{ transport: transportType, logger: logger }),
|
||||
logger,
|
||||
protocol);
|
||||
|
||||
hubConnection.onClosed = error => {
|
||||
expect(error).toBe(undefined);
|
||||
done();
|
||||
|
|
@ -65,8 +74,13 @@ describe('hubConnection', () => {
|
|||
|
||||
it(`rethrows an exception from the server when invoking`, done => {
|
||||
const errorMessage = "An error occurred.";
|
||||
let hubConnection = new signalR.HubConnection(
|
||||
new signalR.HttpConnection(TESTHUBENDPOINT_URL, { transport: transportType }), protocol);
|
||||
|
||||
let logger = new signalR.ConsoleLogger(signalR.LogLevel.Information);
|
||||
let hubConnection = new signalR.HubConnection(new signalR.HttpConnection(
|
||||
TESTHUBENDPOINT_URL,
|
||||
{ transport: transportType, logger: logger }),
|
||||
logger,
|
||||
protocol);
|
||||
|
||||
hubConnection.start()
|
||||
.then(() => {
|
||||
|
|
@ -93,8 +107,13 @@ describe('hubConnection', () => {
|
|||
|
||||
it(`rethrows an exception from the server when streaming`, done => {
|
||||
const errorMessage = "An error occurred.";
|
||||
let hubConnection = new signalR.HubConnection(
|
||||
new signalR.HttpConnection(TESTHUBENDPOINT_URL, { transport: transportType }), protocol);
|
||||
|
||||
let logger = new signalR.ConsoleLogger(signalR.LogLevel.Information);
|
||||
let hubConnection = new signalR.HubConnection(new signalR.HttpConnection(
|
||||
TESTHUBENDPOINT_URL,
|
||||
{ transport: transportType, logger: logger }),
|
||||
logger,
|
||||
protocol);
|
||||
|
||||
hubConnection.start()
|
||||
.then(() => {
|
||||
|
|
@ -120,20 +139,25 @@ describe('hubConnection', () => {
|
|||
});
|
||||
|
||||
it(`can receive server calls`, done => {
|
||||
let client = new signalR.HubConnection(
|
||||
new signalR.HttpConnection(TESTHUBENDPOINT_URL, { transport: transportType }), protocol);
|
||||
let logger = new signalR.ConsoleLogger(signalR.LogLevel.Information);
|
||||
let hubConnection = new signalR.HubConnection(new signalR.HttpConnection(
|
||||
TESTHUBENDPOINT_URL,
|
||||
{ transport: transportType, logger: logger }),
|
||||
logger,
|
||||
protocol);
|
||||
|
||||
const message = "你好 SignalR!";
|
||||
|
||||
let callbackPromise = new Promise((resolve, reject) => {
|
||||
client.on("Message", msg => {
|
||||
hubConnection.on("Message", msg => {
|
||||
expect(msg).toBe(message);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
client.start()
|
||||
hubConnection.start()
|
||||
.then(() => {
|
||||
return Promise.all([client.invoke('InvokeWithString', message), callbackPromise]);
|
||||
return Promise.all([hubConnection.invoke('InvokeWithString', message), callbackPromise]);
|
||||
})
|
||||
.then(() => {
|
||||
return stop();
|
||||
|
|
@ -154,8 +178,12 @@ describe('hubConnection', () => {
|
|||
ServerSentEvents: "Error occurred"
|
||||
};
|
||||
|
||||
let hubConnection = new signalR.HubConnection(
|
||||
new signalR.HttpConnection(`http://${document.location.host}/uncreatable`, { transport: transportType }), protocol);
|
||||
let logger = new signalR.ConsoleLogger(signalR.LogLevel.Information);
|
||||
let hubConnection = new signalR.HubConnection(new signalR.HttpConnection(
|
||||
`http://${document.location.host}/uncreatable`,
|
||||
{ transport: transportType, logger: logger }),
|
||||
logger,
|
||||
protocol);
|
||||
|
||||
hubConnection.onClosed = error => {
|
||||
expect(error.message).toMatch(errorRegex[signalR.TransportType[transportType]]);
|
||||
|
|
|
|||
Loading…
Reference in New Issue