Skip to content

Commit

Permalink
improve logging
Browse files Browse the repository at this point in the history
  • Loading branch information
prostgles committed May 15, 2024
1 parent f4fe293 commit fd8810d
Show file tree
Hide file tree
Showing 11 changed files with 192 additions and 134 deletions.
12 changes: 12 additions & 0 deletions lib/AuthHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,18 @@ export default class AuthHandler {
}
}

/**
* Used for logging
*/
getSIDNoError = (localParams: LocalParams | undefined): string | undefined => {
if(!localParams) return undefined;
try {
return this.getSID(localParams);
} catch (err) {
return undefined;
}
}

async getClientInfo(localParams: Pick<LocalParams, "socket" | "httpReq">): Promise<AuthResult> {
if (!this.opts) return {};

Expand Down
3 changes: 2 additions & 1 deletion lib/DboBuilder/DboBuilderTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,8 @@ export type LocalParams = {
t: pgPromise.ITask<{}>;
}

// localTX?: pgPromise.ITask<{}>;
/** Used to exclude certain logs */
noLog?: boolean;

returnQuery?: boolean | "noRLS" | "where-condition";
returnNewQuery?: boolean;
Expand Down
9 changes: 8 additions & 1 deletion lib/DboBuilder/ViewHandler/ViewHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,14 @@ export class ViewHandler {
}

_log = ({ command, data, localParams, duration, error }: Pick<TableEvent, "command" | "data" | "localParams"> & { duration: number; error?: any; }) => {
return this.dboBuilder.prostgles.opts.onLog?.({ type: "table", tableName: this.name, command, data, localParams, duration, error });
if(localParams?.noLog){
if(localParams?.socket || localParams.httpReq) {
throw new Error("noLog option is not allowed from a remote client");
}
return;
}
const sid = this.dboBuilder.prostgles.authHandler?.getSIDNoError(localParams);
return this.dboBuilder.prostgles.opts.onLog?.({ type: "table", sid, socketId: localParams?.socket?.id, tableName: this.name, command, data, localParams, duration, error });
}

getRowHashSelect(allowedFields: FieldFilter, alias?: string, tableAlias?: string): string {
Expand Down
44 changes: 27 additions & 17 deletions lib/Logging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { LocalParams } from "./DboBuilder/DboBuilder";
import { TableHandler } from "./DboBuilder/TableHandler/TableHandler";

type ClientInfo = {
socketId: string;
socketId: string | undefined;
sid: string | undefined;
}

Expand All @@ -13,32 +13,21 @@ export namespace EventTypes {
error?: any;
}

export type Table = {
export type Table = ClientInfo & DebugInfo & {
type: "table";
tableName: string;
command: keyof TableHandler;
data: AnyObject;
localParams: LocalParams | undefined;
duration: number;
error?: any;
};

export type Sync = {
type SyncOneClient = ClientInfo & DebugInfo & {
type: "sync";
tableName: string;
localParams?: LocalParams;
connectedSocketIds: string[];
duration?: number;
error?: any;
} & (
{
command: "notifListener";
op_name: string | undefined;
condition_ids_str: string | undefined;
tableTriggers: string[] | undefined;
tableSyncs: string;
state: "ok" | "error" | "no-triggers" | "invalid_condition_ids";
} | {
command: "syncData";
source: "client" | "trigger";
connectedSocketIds: string[];
Expand All @@ -65,16 +54,36 @@ export namespace EventTypes {
connectedSocketIds: string[];
}
);
export type SyncMultiClient = {
type: "sync";
tableName: string;
localParams?: LocalParams;
connectedSocketIds: string[];
} & (
{
command: "notifListener";
op_name: string | undefined;
condition_ids_str: string | undefined;
tableTriggers: string[] | undefined;
tableSyncs: string;
state: "ok" | "error" | "no-triggers" | "invalid_condition_ids";
}
);

export type Sync = SyncOneClient | SyncMultiClient;

export type Connection = ClientInfo & {
export type Connection = (ClientInfo & {
type: "connect" | "disconnect";
socketId: string;
connectedSocketIds: string[];
};
}) | (ClientInfo & DebugInfo & {
type: "connect.getClientSchema";
});

export type Method = {
export type Method = ClientInfo & DebugInfo & {
type: "method";
args: any[];
localParams: LocalParams;
};

export type Debug = DebugInfo & {
Expand Down Expand Up @@ -102,6 +111,7 @@ export type EventInfo =
| EventTypes.Table
| EventTypes.Method
| EventTypes.Sync
| EventTypes.SyncMultiClient
| EventTypes.Connection
| EventTypes.Debug;

Expand Down
141 changes: 81 additions & 60 deletions lib/Prostgles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -384,17 +384,17 @@ export class Prostgles {
type: "debug",
command: "refreshDBO.start",
duration: -1,
data: { work_mem: await this.db?.oneOrNone(`show work_mem;`) }
data: { }
});
const now = Date.now();
const start = Date.now();
if (this._dboBuilder) {
await this._dboBuilder.build();
} else {
this.dboBuilder = await DboBuilder.create(this);
}
if (!this.dboBuilder) throw "this.dboBuilder";
this.dbo = this.dboBuilder.dbo;
await this.opts.onLog?.({ type: "debug", command: "refreshDBO.end", duration: Date.now() - now })
await this.opts.onLog?.({ type: "debug", command: "refreshDBO.end", duration: Date.now() - start })
return this.dbo;
}

Expand Down Expand Up @@ -429,7 +429,7 @@ export class Prostgles {
}
});
await this.opts.onLog?.({ type: "debug", command: "initTableConfig", ...res });
if(res.error !== undefined) throw res.error;
if(res.hasError) throw res.error;
return res.data;
}

Expand Down Expand Up @@ -619,70 +619,91 @@ export class Prostgles {
}

getClientSchema = async (clientReq: Pick<LocalParams, "socket" | "httpReq">) => {
const clientInfo = clientReq.socket? { type: "socket" as const, socket: clientReq.socket } : clientReq.httpReq? { type: "http" as const, httpReq: clientReq.httpReq } : undefined;
if(!clientInfo) throw "Invalid client";
if(!this.authHandler) throw "this.authHandler missing";
const userData = await this.authHandler.getClientInfo(clientInfo);
const { publishParser } = this;
let fullSchema: {
schema: TableSchemaForClient;
tables: DBSchemaTable[];
} | undefined;
let publishValidationError;

try {
if (!publishParser) throw "publishParser undefined";
fullSchema = await publishParser.getSchemaFromPublish({ ...clientInfo, userData });
} catch (e) {
publishValidationError = "Server Error: PUBLISH VALIDATION ERROR";
console.error(`\nProstgles PUBLISH VALIDATION ERROR (after socket connected):\n ->`, e);
}
let rawSQL = false;
if (this.opts.publishRawSQL && typeof this.opts.publishRawSQL === "function") {
const { allowed } = await clientCanRunSqlRequest.bind(this)(clientInfo);
rawSQL = allowed;
}
const result = await tryCatch(async () => {

const { schema, tables } = fullSchema ?? { schema: {}, tables: [] };
const joinTables2: string[][] = [];
if (this.opts.joins) {
const _joinTables2 = this.dboBuilder.getAllJoinPaths()
.filter(jp =>
![jp.t1, jp.t2].find(t => !schema[t] || !schema[t]?.findOne)
).map(jp => [jp.t1, jp.t2].sort());
_joinTables2.map(jt => {
if (!joinTables2.find(_jt => _jt.join() === jt.join())) {
joinTables2.push(jt);
}
});
}
const clientInfo = clientReq.socket? { type: "socket" as const, socket: clientReq.socket } : clientReq.httpReq? { type: "http" as const, httpReq: clientReq.httpReq } : undefined;
if(!clientInfo) throw "Invalid client";
if(!this.authHandler) throw "this.authHandler missing";
const userData = await this.authHandler.getClientInfo(clientInfo);

const methods = await publishParser?.getAllowedMethods(clientInfo, userData);
const { publishParser } = this;
let fullSchema: {
schema: TableSchemaForClient;
tables: DBSchemaTable[];
} | undefined;
let publishValidationError;

const methodSchema: ClientSchema["methods"] = !methods? [] : getKeys(methods).map(methodName => {
const method = methods[methodName];
try {
if (!publishParser) throw "publishParser undefined";
fullSchema = await publishParser.getSchemaFromPublish({ ...clientInfo, userData });
} catch (e) {
publishValidationError = e;
console.error(`\nProstgles Publish validation failed (after socket connected):\n ->`, e);
}
let rawSQL = false;
if (this.opts.publishRawSQL && typeof this.opts.publishRawSQL === "function") {
const { allowed } = await clientCanRunSqlRequest.bind(this)(clientInfo);
rawSQL = allowed;
}

if(isObject(method) && "run" in method){
return {
name: methodName,
...omitKeys(method, ["run"]),
const { schema, tables } = fullSchema ?? { schema: {}, tables: [] };
const joinTables2: string[][] = [];
if (this.opts.joins) {
const _joinTables2 = this.dboBuilder.getAllJoinPaths()
.filter(jp =>
![jp.t1, jp.t2].find(t => !schema[t] || !schema[t]?.findOne)
).map(jp => [jp.t1, jp.t2].sort());
_joinTables2.map(jt => {
if (!joinTables2.find(_jt => _jt.join() === jt.join())) {
joinTables2.push(jt);
}
});
}

const methods = await publishParser?.getAllowedMethods(clientInfo, userData);

const methodSchema: ClientSchema["methods"] = !methods? [] : getKeys(methods).map(methodName => {
const method = methods[methodName];

if(isObject(method) && "run" in method){
return {
name: methodName,
...omitKeys(method, ["run"]),
}
}
return methodName;
});

const { auth } = clientReq.socket? await this.authHandler.makeSocketAuth(clientReq.socket) : { auth: {} };

const clientSchema: ClientSchema = {
schema,
methods: methodSchema,
tableSchema: tables,
rawSQL,
joinTables: joinTables2,
auth,
version,
err: publishValidationError? "Server Error: User publish validation failed." : undefined
};

return {
publishValidationError,
clientSchema,
userData
}
return methodName;
});

const { auth } = clientReq.socket? await this.authHandler.makeSocketAuth(clientReq.socket) : { auth: {} };
const clientSchema: ClientSchema = {
schema,
methods: methodSchema,
tableSchema: tables,
rawSQL,
joinTables: joinTables2,
auth,
version,
err: publishValidationError
}
return clientSchema;
const sid = result.userData?.sid ?? this.authHandler?.getSIDNoError(clientReq);
await this.opts.onLog?.({
type: "connect.getClientSchema",
duration: result.duration,
sid,
socketId: clientReq.socket?.id,
error: result.error || result.publishValidationError,
});
if(result.hasError) throw result.error;
return result.clientSchema;
}

pushSocketSchema = async (socket: PRGLIOSocket) => {
Expand Down
3 changes: 3 additions & 0 deletions lib/PubSubManager/PubSubManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export type BasicCallback = (err?: any, res?: any) => void

export type SyncParams = {
socket_id: string;
sid: string | undefined;
channel_name: string;
table_name: string;
table_rules?: TableRule;
Expand Down Expand Up @@ -375,6 +376,7 @@ export class PubSubManager {
command: "upsertSocket.disconnect",
tableName: "",
duration: 0,
sid: this.dboBuilder.prostgles.authHandler?.getSIDNoError({ socket }),
socketId: socket.id,
connectedSocketIds: this.connectedSocketIds,
remainingSubs: JSON.stringify(this.subs.map(s => ({ tableName: s.table_info.name, triggers: s.triggers }))),
Expand Down Expand Up @@ -498,6 +500,7 @@ export class PubSubManager {
socketId: socket?.id,
state: !addedTrigger.tbl? "fail" : "ok",
error: addedTrigger.error,
sid: this.dboBuilder.prostgles.authHandler?.getSIDNoError({ socket }),
tableName: addedTrigger.tbl ?? params.table_name,
connectedSocketIds: this.dboBuilder.prostgles.connectedSockets.map(s => s.id),
localParams: { socket }
Expand Down
Loading

0 comments on commit fd8810d

Please sign in to comment.