From f4589aa96e32365d7b9fd4d657a398a223eae37d Mon Sep 17 00:00:00 2001 From: Peter Maquiran Date: Mon, 22 Jul 2024 13:28:52 +0100 Subject: [PATCH] add opentelemetr logging --- gabinete-digital-fo.code-workspace | 10 ++++ .../message-live-data-source.service.ts | 18 +++--- .../room/room-live-data-source.service.ts | 20 +++---- .../room/room-remote-data-source.service.ts | 3 +- .../repository/message-respository.service.ts | 12 ++-- .../repository/room-repository.service.ts | 16 ++--- src/app/module/chat/infra/socket/socket.ts | 14 ++--- src/app/pages/chat/chat.page.ts | 16 ++--- .../monitoring/opentelemetry/logging.ts | 26 ++++++++ .../monitoring/opentelemetry/opentelemetry.ts | 53 +++++++++++++++++ .../monitoring/opentelemetry/tracer.ts | 51 ++++++++++++++-- src/app/services/monitoring/socket/socket.ts | 59 +++++++++++++++++++ 12 files changed, 243 insertions(+), 55 deletions(-) create mode 100644 src/app/services/monitoring/opentelemetry/logging.ts create mode 100644 src/app/services/monitoring/socket/socket.ts diff --git a/gabinete-digital-fo.code-workspace b/gabinete-digital-fo.code-workspace index ed1b28b09..ea33f72b6 100644 --- a/gabinete-digital-fo.code-workspace +++ b/gabinete-digital-fo.code-workspace @@ -1,21 +1,31 @@ { "folders": [ { + "name": "gabinete-digital-fo", "path": "." }, { + "name": "oo", + "path": "../../../Downloads/oo" + }, + { + "name": "socket-server", "path": "../socket-server" }, { + "name": "logs", "path": "../logs" }, { + "name": "opentelemetry-js-main", "path": "../../../Downloads/opentelemetry-js-main/opentelemetry-js-main" }, { + "name": "grayLog", "path": "../grayLog" }, { + "name": "equilibriumito-gabinete-digital-fo-23cf0fc4cbaa", "path": "../../../Downloads/equilibriumito-gabinete-digital-fo-23cf0fc4cbaa/equilibriumito-gabinete-digital-fo-23cf0fc4cbaa" } ], diff --git a/src/app/module/chat/data/data-source/message/message-live-data-source.service.ts b/src/app/module/chat/data/data-source/message/message-live-data-source.service.ts index 7e70c34c1..2ddde368f 100644 --- a/src/app/module/chat/data/data-source/message/message-live-data-source.service.ts +++ b/src/app/module/chat/data/data-source/message/message-live-data-source.service.ts @@ -8,20 +8,20 @@ import { SignalRService } from '../../../infra/socket/signal-r.service'; export class MessageLiveDataSourceService { constructor( - public socket: WebSocketService, + // public socket: WebSocketService, private signalR: SignalRService) {} - async sendMessage(data: WebSocketMessage) { + // async sendMessage(data: WebSocketMessage) { - try { + // // try { - const result = await this.socket.sendMessage(data).toPromise() + // // const result = await this.socket.sendMessage(data).toPromise() - return ok(result) - } catch (e) { - return err(e) - } + // // return ok(result) + // // } catch (e) { + // // return err(e) + // // } - } + // } } diff --git a/src/app/module/chat/data/data-source/room/room-live-data-source.service.ts b/src/app/module/chat/data/data-source/room/room-live-data-source.service.ts index 2fff9870f..f2f9a6ed7 100644 --- a/src/app/module/chat/data/data-source/room/room-live-data-source.service.ts +++ b/src/app/module/chat/data/data-source/room/room-live-data-source.service.ts @@ -7,21 +7,21 @@ import { err, ok } from 'neverthrow'; }) export class RoomLiveDataSourceService { - constructor(private socket: WebSocketService) {} + // constructor(private socket: WebSocketService) {} - async getRoomById(data: WebSocketMessage) { + // async getRoomById(data: WebSocketMessage) { - try { + // try { - const result = await this.socket.sendMessage(data).toPromise() + // const result = await this.socket.sendMessage(data).toPromise() - console.log({result}) + // console.log({result}) - return ok(result) - } catch (e) { - return err(e) - } + // return ok(result) + // } catch (e) { + // return err(e) + // } - } + // } } diff --git a/src/app/module/chat/data/data-source/room/room-remote-data-source.service.ts b/src/app/module/chat/data/data-source/room/room-remote-data-source.service.ts index b9b777fc5..270be2b6b 100644 --- a/src/app/module/chat/data/data-source/room/room-remote-data-source.service.ts +++ b/src/app/module/chat/data/data-source/room/room-remote-data-source.service.ts @@ -13,6 +13,7 @@ import { UserRemoveListInputDTO, UserRemoveListInputDTOSchema } from '../../dto/ import { RoomUpdateInputDTO, RoomUpdateInputDTOSchema } from '../../dto/room/roomUpdateInputDTO'; import { RoomUpdateOutputDTO } from '../../dto/room/roomUpdateOutputDTO'; import { DataSourceReturn } from 'src/app/services/Repositorys/type'; +import { SessionStore } from 'src/app/store/session.service'; @Injectable({ providedIn: 'root' @@ -33,7 +34,7 @@ export class RoomRemoteDataSourceService { @APIReturn(RoomListOutPutDTOSchema, 'get/Room') async getRoomList(): Promise> { - return await this.httpService.get(`${this.baseUrl}/Room`); + return await this.httpService.get(`${this.baseUrl}/Room?userId=${SessionStore.user.UserId}`); } @ValidateSchema(RoomByIdInputDTOSchema) 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 3e8a61746..acd679e12 100644 --- a/src/app/module/chat/data/repository/message-respository.service.ts +++ b/src/app/module/chat/data/repository/message-respository.service.ts @@ -22,12 +22,12 @@ export class MessageRepositoryService { private messageLiveSignalRDataSourceService: SignalRService, private messageLocalDataSourceService: MessageLocalDataSourceService ) { - this.messageLiveDataSourceService.socket.messages$.subscribe(({payload, requestId, type}) => { + // this.messageLiveDataSourceService.socket.messages$.subscribe(({payload, requestId, type}) => { - }) + // }) } @@ -44,10 +44,10 @@ export class MessageRepositoryService { const localActionResult = await this.messageLocalDataSourceService.sendMessage(data) - this.messageLiveDataSourceService.sendMessage({ - type: 'sendMessage', - payload: data - }) + // this.messageLiveDataSourceService.sendMessage({ + // type: 'sendMessage', + // payload: data + // }) if(localActionResult.isOk()) { diff --git a/src/app/module/chat/data/repository/room-repository.service.ts b/src/app/module/chat/data/repository/room-repository.service.ts index 891cbdf5e..5bdd88347 100644 --- a/src/app/module/chat/data/repository/room-repository.service.ts +++ b/src/app/module/chat/data/repository/room-repository.service.ts @@ -170,10 +170,10 @@ export class RoomRepositoryService { if(result.isOk()) { const result = await this.roomLocalDataSourceService.deleteRoomById(id) - this.messageLiveDataSourceService.sendMessage({ - type: 'createRoom', - payload: {a: '5'} - }) + // this.messageLiveDataSourceService.sendMessage({ + // type: 'createRoom', + // payload: {a: '5'} + // }) return result } else if (isHttpResponse(result.error)) { @@ -216,10 +216,10 @@ export class RoomRepositoryService { // this.roomMemoryDataSourceService.dispatch(addRoom(result.value)) const localResult = await this.roomLocalDataSourceService.createRoom(result.value.data) - this.messageLiveDataSourceService.sendMessage({ - type: 'createRoom', - payload: {a: '5'} - }) + // this.messageLiveDataSourceService.sendMessage({ + // type: 'createRoom', + // payload: {a: '5'} + // }) return localResult.map(e => result.value) } diff --git a/src/app/module/chat/infra/socket/socket.ts b/src/app/module/chat/infra/socket/socket.ts index f8981d340..815029b1a 100644 --- a/src/app/module/chat/infra/socket/socket.ts +++ b/src/app/module/chat/infra/socket/socket.ts @@ -33,16 +33,16 @@ export class WebSocketService { this.messageSubject$ = new Subject(); this.connectionStatus$ = new BehaviorSubject(false); - this.connect('https://5-180-182-151.cloud-xip.com:85/ws/') + // this.connect('https://5-180-182-151.cloud-xip.com:85/ws/') - this.messages$.subscribe(({payload, requestId, type}) => { - if(this.callback[requestId]) { - this.callback[requestId]({payload, requestId, type}) - delete this.callback[requestId] + // this.messages$.subscribe(({payload, requestId, type}) => { + // if(this.callback[requestId]) { + // this.callback[requestId]({payload, requestId, type}) + // delete this.callback[requestId] - } - }) + // } + // }) } public connect(url: string) { diff --git a/src/app/pages/chat/chat.page.ts b/src/app/pages/chat/chat.page.ts index a2806c327..b806390cc 100644 --- a/src/app/pages/chat/chat.page.ts +++ b/src/app/pages/chat/chat.page.ts @@ -124,16 +124,16 @@ export class ChatPage implements OnInit { ) { - this.messageLiveDataSourceService.socket.messages$.subscribe(({payload, requestId, type}) => { - if(payload.sender == null) { - delete payload.sender - } + // this.messageLiveDataSourceService.socket.messages$.subscribe(({payload, requestId, type}) => { + // if(payload.sender == null) { + // delete payload.sender + // } - if(type == 'createRoom') { - this.RoomRepositoryService.list(); - } + // if(type == 'createRoom') { + // this.RoomRepositoryService.list(); + // } - }) + // }) this.headers = new HttpHeaders(); window.onresize = (event) => { diff --git a/src/app/services/monitoring/opentelemetry/logging.ts b/src/app/services/monitoring/opentelemetry/logging.ts new file mode 100644 index 000000000..72903ab59 --- /dev/null +++ b/src/app/services/monitoring/opentelemetry/logging.ts @@ -0,0 +1,26 @@ +import { Injectable } from "@angular/core"; +import { v4 as uuidv4 } from 'uuid'; +import { WebSocketGraylogService } from "../socket/socket"; +import { Span } from "@opentelemetry/sdk-trace-web"; + + +export class OpenTelemetryLogging { + + socket = new WebSocketGraylogService() + + constructor() { + this.socket.start() + } + + send(data: Object & { type: string; payload: any, spanContext:any }): void { + this.socket.send({ + type: data.type, + payload: data.payload, + requestId: uuidv4(), + spanContext: data.spanContext + }); + } + +} + +export const openTelemetryLogging = new OpenTelemetryLogging() diff --git a/src/app/services/monitoring/opentelemetry/opentelemetry.ts b/src/app/services/monitoring/opentelemetry/opentelemetry.ts index d6d872536..991acda00 100644 --- a/src/app/services/monitoring/opentelemetry/opentelemetry.ts +++ b/src/app/services/monitoring/opentelemetry/opentelemetry.ts @@ -3,6 +3,7 @@ import { WebTracerProvider } from '@opentelemetry/sdk-trace-web'; import { ZipkinExporter } from '@opentelemetry/exporter-zipkin'; import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions' import { Resource } from '@opentelemetry/resources'; +import { context, trace, propagation } from '@opentelemetry/api'; function createProvider(serviceName) { const provider = new WebTracerProvider({ @@ -32,3 +33,55 @@ 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'); +export const OpentelemetryLogging = createProvider('logging'); + + +const tracerInstance = OpentelemetryAgendaProvider.getTracer('example-tracer-hole', '111', {}) + + +function parentSpanExample() { + // Create a tracer instance + const tracer = trace.getTracer('FO-chat-service'); + + // Start a parent span + const parentSpan = tracer.startSpan('parent-span'); + parentSpan.setAttribute('key', 'value') + + const traceId = parentSpan.spanContext().traceId; + const spanId = parentSpan.spanContext().spanId; + parentSpan.end(); // End the parent span + + const spanContext = { + traceId: traceId, + spanId: spanId, + traceFlags: 1 // 1 means the trace is sampled + }; + + // Create a new context with the parent span + const parentContext = trace.setSpan(context.active(), parentSpan); + const parentContext1 = trace.setSpan(context.active(), trace.wrapSpanContext(spanContext)); + + // Start a new child span + const childSpan = tracer.startSpan('child-span1', {root: false}, parentContext1); + childSpan.end(); + + // Simulate some work + setTimeout(() => { + childSpanExample(parentContext); // Pass the context to child span + + }, 500); +} + + +function childSpanExample(parentContext) { + // Create a new child span with the parent context + const tracer = trace.getTracer('FO-chat-service'); + const childSpan = tracer.startSpan('child-span', undefined, parentContext); + + // Simulate some work + setTimeout(() => { + childSpan.end(); // End the child span + }, 500); +} + +parentSpanExample() diff --git a/src/app/services/monitoring/opentelemetry/tracer.ts b/src/app/services/monitoring/opentelemetry/tracer.ts index d4c0ff358..b09f863b9 100644 --- a/src/app/services/monitoring/opentelemetry/tracer.ts +++ b/src/app/services/monitoring/opentelemetry/tracer.ts @@ -1,11 +1,12 @@ import { v4 as uuidv4 } from 'uuid'; import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; import { Tracer, Span } from '@opentelemetry/sdk-trace-base'; -import { OpentelemetryAgendaProvider, OpentelemetryInterceptorProvider, OpentelemetryNotificationProvider } from './opentelemetry'; +import { OpentelemetryAgendaProvider, OpentelemetryInterceptorProvider, OpentelemetryLogging, OpentelemetryNotificationProvider } from './opentelemetry'; import { Device, DeviceInfo } from '@capacitor/device'; import { SessionStore } from 'src/app/store/session.service'; import { environment } from 'src/environments/environment'; import { UseCaseCounter } from './matrix'; +import { openTelemetryLogging } from './logging'; // import { context, propagation } from '@opentelemetry/api'; const tracerInstance = OpentelemetryAgendaProvider.getTracer('example-tracer-hole', '111', {}) @@ -18,6 +19,25 @@ Device.getInfo().then(e => { device = e }); +function convertAttributesToString(obj) { + const result = {}; + + for (const key in obj) { + if (obj.hasOwnProperty(key)) { + if (typeof obj[key] === 'object' && obj[key] !== null) { + // Convert only the object attribute to string + result[key] = JSON.stringify(obj[key], null, 2); + } else { + // Convert primitive values to string + result[key] = String(obj[key]); + } + } + } + + return result; +} + + const createTracingInstance = ({bugPrint, name, module, autoFinish}): TracingType => { const requestId = uuidv4() @@ -30,7 +50,6 @@ const createTracingInstance = ({bugPrint, name, module, autoFinish}): TracingTyp } const span = _tracerInstance.startSpan(name); - let hasBug:Boolean const data = { event: {}, @@ -63,6 +82,28 @@ const createTracingInstance = ({bugPrint, name, module, autoFinish}): TracingTyp span.setAttribute('error', 'true') } }, + log(message: string, data: Object) { + const spanId = span.spanContext().spanId; + const _tracer = OpentelemetryLogging.getTracer('logging') + const spanContext = _tracer.startSpan(name) + + data = convertAttributesToString(data) + openTelemetryLogging.send({ + type: 'graylog', + spanContext, + payload: { + message: message, + object: { + ...data, + spanId, + name, + user: SessionStore?.user?.FullName, + device_name: device?.name || device?.model, + commit_date: environment.version.lastCommitTime, + } + } + }) + }, getAttribute: (key: string) => { return data.tags[key] }, @@ -76,9 +117,7 @@ const createTracingInstance = ({bugPrint, name, module, autoFinish}): TracingTyp console.error(name, data) } }, - bugFlag:() => { - hasBug = true - }, + bugFlag:() => {}, createSpan: (name, parent?: any) => { return tracerInstance.startSpan(name, { root: false }, parent) as Span; } @@ -176,7 +215,7 @@ export type TracingType = { attributes: typeof SemanticAttributes; // axios: (config?: AxiosRequestConfig) => AxiosInstance; setStatus: (status: any) => void; - //logEvent: (name: string, attributesOrStartTime?: AttributeValue | TimeInput) => void; + log: (message: string, data: Object) => void; addEvent: (context: string, message?: any, obj?: any) => void; setAttribute: (key: string, value: string) => void; getAttribute: (key: string) => string; diff --git a/src/app/services/monitoring/socket/socket.ts b/src/app/services/monitoring/socket/socket.ts new file mode 100644 index 000000000..a86c0886c --- /dev/null +++ b/src/app/services/monitoring/socket/socket.ts @@ -0,0 +1,59 @@ + +import { Injectable } from '@angular/core'; +import { v4 as uuidv4 } from 'uuid'; + +@Injectable({ + providedIn: 'root' +}) +export class WebSocketGraylogService { + private adminSocketGlobal!: WebSocket; + connected = false + + constructor() { } + + connect(): void { + this.adminSocketGlobal = new WebSocket('wss://5-180-182-151.cloud-xip.com:85/ws/'); + + this.adminSocketGlobal.onopen = () => { + console.log('Admin WebSocket is open now.'); + this.adminSocketGlobal.send("uuid"); + this.connected = true + }; + + this.adminSocketGlobal.onmessage = async (event: MessageEvent) => { + // Handle incoming messages here + }; + + this.adminSocketGlobal.onclose = () => { + console.log('Admin WebSocket is closed now.'); + this.connect(); + }; + + this.adminSocketGlobal.onerror = (error: Event) => { + console.error('Admin WebSocket error:', error); + }; + } + + send(data: Object & { type: string; payload: Object , requestId: string, spanContext:any }): void { + if (this.adminSocketGlobal.readyState === WebSocket.OPEN) { + + this.adminSocketGlobal.send(JSON.stringify({ + type: data.type , + payload: data.payload, + requestId: data.requestId, + parentSpan: { + traceId: data.spanContext.spanContext().traceId, + spanId: data.spanContext.spanContext().spanId, + } + })); + + // data.spanContext.end() + } else { + console.warn('WebSocket is not open. Message not sent.'); + } + } + + start(): void { + this.connect(); + } +}