diff --git a/gabinete-digital-fo.code-workspace b/gabinete-digital-fo.code-workspace index ae4388414..ed1b28b09 100644 --- a/gabinete-digital-fo.code-workspace +++ b/gabinete-digital-fo.code-workspace @@ -16,7 +16,7 @@ "path": "../grayLog" }, { - "path": "../../../Downloads/equilibriumito-gabinete-digital-fo-4f51cb55504b" + "path": "../../../Downloads/equilibriumito-gabinete-digital-fo-23cf0fc4cbaa/equilibriumito-gabinete-digital-fo-23cf0fc4cbaa" } ], "settings": { diff --git a/src/app/module/chat/data/async/socket/message-async.service.ts b/src/app/module/chat/data/async/socket/message-async.service.ts index 0a9974929..9beafcc35 100644 --- a/src/app/module/chat/data/async/socket/message-async.service.ts +++ b/src/app/module/chat/data/async/socket/message-async.service.ts @@ -1,10 +1,12 @@ import { Injectable } from '@angular/core'; import { MessageLiveDataSourceService } from '../../data-source/message/message-live-data-source.service'; -import { MessageLocalDataSourceService } from '../../data-source/message/message-local-data-source.service'; +import { IncomingMessageSchema, MessageLocalDataSourceService } from '../../data-source/message/message-local-data-source.service'; import { MessageRemoteDataSourceService } from '../../data-source/message/message-remote-data-source.service'; import { SignalRService } from '../../../infra/socket/signal-r.service'; import { filter } from 'rxjs/operators'; import { InstanceId } from '../../repository/message-respository.service'; +import { SocketStreamReturn } from 'src/app/services/decorators/socket-validate-schema.decorator'; +import { SafeValidateSchema } from 'src/app/services/decorators/validate-schema.decorator'; @Injectable({ providedIn: 'root' @@ -26,25 +28,33 @@ export class MessageAsyncService { ).subscribe(async (message: any) => { console.log('message async ', message) - const id = message.id + + const id = message.id + '' delete message.id; - const result = await this.messageLocalDataSourceService.createMessage({ + const incomingMessage = { + ...message, messageId: id, sending: false, - ...message - }) - - if(result.isOk()) { - - console.log(result.value) - console.log("nice send receive") - - } else { - console.log(result.error) + roomId:message.chatRoomId } + this.incomingMessage(incomingMessage) + + }) } + + @SafeValidateSchema(IncomingMessageSchema, 'socket/incomingMessage') + async incomingMessage(IncomingMessageSchema: any) { + + const result = await this.messageLocalDataSourceService.sendMessage(IncomingMessageSchema) + + if(result.isOk()) { + + } else { + console.log(result.error) + } + } } diff --git a/src/app/module/chat/data/data-source/message/message-local-data-source.service.ts b/src/app/module/chat/data/data-source/message/message-local-data-source.service.ts index 3ae74a9ec..ad9acb338 100644 --- a/src/app/module/chat/data/data-source/message/message-local-data-source.service.ts +++ b/src/app/module/chat/data/data-source/message/message-local-data-source.service.ts @@ -11,7 +11,24 @@ const tableSchema = z.object({ id: z.any().optional(), messageId: z.string().optional(), roomId: z.string().uuid(), - senderId: z.number(), + message: z.string(), + messageType: z.number(), + canEdit: z.boolean(), + oneShot: z.boolean(), + sentAt: z.string().optional(), + requireUnlock: z.boolean(), + sender: z.object({ + wxUserId: z.number(), + wxFullName: z.string(), + wxeMail: z.string(), + userPhoto: z.string(), + }), + sending: z.boolean().optional() +}) + +export const IncomingMessageSchema = z.object({ + messageId: z.string().optional(), + roomId: z.string().uuid(), message: z.string(), messageType: z.number(), canEdit: z.boolean(), @@ -36,7 +53,7 @@ export const messageDataSource = new Dexie('chat-message') as Dexie & { }; messageDataSource.version(1).stores({ - message: '++id, roomId, senderId, message, messageType, canEdit, oneShot, requireUnlock, messageId' + message: '++id, roomId, message, messageType, canEdit, oneShot, requireUnlock, messageId' }); @Injectable({ diff --git a/src/app/module/chat/data/repository/message-respository.service.ts b/src/app/module/chat/data/repository/message-respository.service.ts index e1cf047a2..22d76c5f5 100644 --- a/src/app/module/chat/data/repository/message-respository.service.ts +++ b/src/app/module/chat/data/repository/message-respository.service.ts @@ -6,6 +6,7 @@ import { MessageLocalDataSourceService, TableMessage } from '../data-source/mess import { SessionStore } from 'src/app/store/session.service'; import { SignalRService } from '../../infra/socket/signal-r.service'; import { v4 as uuidv4 } from 'uuid' +import { filter } from 'rxjs/operators'; export const InstanceId = uuidv4(); diff --git a/src/app/module/chat/infra/socket/signal-r.service.ts b/src/app/module/chat/infra/socket/signal-r.service.ts index fd4687688..39d6964bd 100644 --- a/src/app/module/chat/infra/socket/signal-r.service.ts +++ b/src/app/module/chat/infra/socket/signal-r.service.ts @@ -43,7 +43,7 @@ export class SignalRService { private async establishConnection() { - const connection = new SignalRConnection({url:'https://gdapi-dev.dyndns.info/stage/chathub'}) + const connection = new SignalRConnection({url:'https://gdapi-dev.dyndns.info/stage/api/v2/chathub'}) const attempConnection = await connection.establishConnection() if(attempConnection.isOk()) { diff --git a/src/app/module/chat/infra/socket/simple.html b/src/app/module/chat/infra/socket/simple.html index 33f21c0e9..d0747bc17 100644 --- a/src/app/module/chat/infra/socket/simple.html +++ b/src/app/module/chat/infra/socket/simple.html @@ -20,7 +20,7 @@ const connection = new signalR.HubConnectionBuilder() .withAutomaticReconnect() - .withUrl("https://gdapi-dev.dyndns.info/stage/chathub") + .withUrl("https://gdapi-dev.dyndns.info/stage/api/v2/chathub") .build(); diff --git a/src/app/services/decorators/socket-validate-schema.decorator.ts b/src/app/services/decorators/socket-validate-schema.decorator.ts new file mode 100644 index 000000000..4ca6e1504 --- /dev/null +++ b/src/app/services/decorators/socket-validate-schema.decorator.ts @@ -0,0 +1,39 @@ +import { HttpErrorResponse } from '@angular/common/http'; +import { Result } from 'neverthrow'; +import { z, ZodError } from 'zod'; +import * as Sentry from '@sentry/capacitor'; +import { ColoredLoggerService } from '../logger/colored/service'; + +export function SocketStreamReturn(schema: z.ZodTypeAny, context: string) { + return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { + const originalMethod = descriptor.value; + + descriptor.value = async function (...args: any[]) { + const result: Result = await originalMethod.apply(this, args); + + if(result.isOk()) { + try { + // Validate the result using the provided schema + schema.parse(result.value); + + } catch (error) { + if (error instanceof ZodError) { + // If validation fails, throw an error with the details + // + ColoredLoggerService.error(error.errors, 'socket unexpected data structure '+ context, schema._def.description) + + } else { + console.log('failed to setup the SocketStreamReturn successful') + // Throw any other unexpected errors + throw error; + } + } + } else { + + } + + return result; + } + return descriptor; + } +} diff --git a/src/app/services/decorators/validate-schema.decorator.ts b/src/app/services/decorators/validate-schema.decorator.ts index bf6a8ae84..b53f760e4 100644 --- a/src/app/services/decorators/validate-schema.decorator.ts +++ b/src/app/services/decorators/validate-schema.decorator.ts @@ -1,5 +1,7 @@ import { err } from 'neverthrow'; -import { Schema } from 'zod'; +import { Schema, ZodError } from 'zod'; +import { ColoredLoggerService } from '../logger/colored/service'; +import { TracingType } from '../monitoring/opentelemetry/tracer'; export function ValidateSchema(schema: Schema) { return ( @@ -14,8 +16,54 @@ export function ValidateSchema(schema: Schema) { args[0] = model; return originalMethod.apply(this, args); } catch (e) { + if (e instanceof ZodError) { + // If validation fails, throw an error with the details + // + ColoredLoggerService.error(e.errors, 'socket unexpected data structure '+ schema._def.description) + + } return err(e) } }; }; } + +export function SafeValidateSchema(schema: Schema, context: string) { + return ( + target: unknown, + propertyKey: string, + descriptor: PropertyDescriptor, + ) => { + const originalMethod = descriptor.value; + descriptor.value = function (...args: unknown[]) { + + const tracing: TracingType = args[args.length - 1] as any; + + try { + const model = schema.parse(args[0]); + args[0] = model; + return originalMethod.apply(this, args); + } catch (e) { + if (e instanceof ZodError) { + // If validation fails, throw an error with the details + // + // If validation fails, throw an error with the details + console.error('unexpected data structure', context) + // Capture the Zod validation error with additional context + console.error('Validation failed:', e.errors); + + tracing?.setAttribute?.('APIReturn.error', 'true') + + let i = 0; + for(const schema of e.errors) { + tracing?.setAttribute?.('map.error.schema-'+i, JSON.stringify(schema)) + } + ColoredLoggerService.error(e.errors, 'socket unexpected data structure '+ context, schema._def.description) + + } + return originalMethod.apply(this, args); + } + }; + }; +} + diff --git a/src/app/services/monitoring/capture-log/capture-log.service.spec.ts b/src/app/services/monitoring/capture-log/capture-log.service.spec.ts new file mode 100644 index 000000000..ee36a2092 --- /dev/null +++ b/src/app/services/monitoring/capture-log/capture-log.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { CaptureLogService } from './capture-log.service'; + +describe('CaptureLogService', () => { + let service: CaptureLogService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(CaptureLogService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/services/monitoring/opentelemetry/opentelemetry.ts b/src/app/services/monitoring/opentelemetry/opentelemetry.ts index fb70ace5a..d6d872536 100644 --- a/src/app/services/monitoring/opentelemetry/opentelemetry.ts +++ b/src/app/services/monitoring/opentelemetry/opentelemetry.ts @@ -32,8 +32,3 @@ export const OpentelemetryAgendaProvider = createProvider('FO-agenda-service'); export const OpentelemetryNotificationProvider = createProvider('FO-notification'); export const OpentelemetryInterceptorProvider = createProvider('FO-interceptor'); export const OpentelemetryPublicationProvider = createProvider('FO-publication-service'); - - - - - diff --git a/src/app/services/monitoring/opentelemetry/tracer.ts b/src/app/services/monitoring/opentelemetry/tracer.ts index bcab1cd38..d4c0ff358 100644 --- a/src/app/services/monitoring/opentelemetry/tracer.ts +++ b/src/app/services/monitoring/opentelemetry/tracer.ts @@ -18,7 +18,6 @@ Device.getInfo().then(e => { device = e }); - const createTracingInstance = ({bugPrint, name, module, autoFinish}): TracingType => { const requestId = uuidv4() @@ -59,6 +58,10 @@ const createTracingInstance = ({bugPrint, name, module, autoFinish}): TracingTyp setAttribute: (key: string, value: string) => { data.tags[key] = value; span.setAttribute(key, value); + + if(key =='outcome' && value == 'failed') { + span.setAttribute('error', 'true') + } }, getAttribute: (key: string) => { return data.tags[key] diff --git a/src/app/shared/chat/messages/messages.page.html b/src/app/shared/chat/messages/messages.page.html index 8eff3d6a0..c5f8ac3d9 100644 --- a/src/app/shared/chat/messages/messages.page.html +++ b/src/app/shared/chat/messages/messages.page.html @@ -16,7 +16,7 @@
- +
@@ -42,8 +42,8 @@
-
{{ message.message }} == {{ message.id }}