You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Is your feature request related to a problem? Please describe.
As a user I would like to track socket events similar to how XHR requests are tracked, in our case, we use the feathers-client and this acts as almost a 2 way REST-API
Describe the solution you'd like
Ideally integrating a class that returns a modified version of the Socket.io client that tracks emit events, responses and responding .on events
import{Socket}from'socket.io-client';import{BASE_URL}from'@env';import{rum}from'#/global/utils/datadog';import{Timer}from'#/global/utils/datadog/Timer';exporttypeFeathersEmitEvents=|'patch'|'create'|'update'|'remove'|'get'|'find';exportinterfaceRumResourceContext{context: {eventType: 'on'|'emit';isSocketIO: boolean;params?: string};method: string;timer: Timer;url: string;}exportinterfaceSocketIOInstrumentationConfig{reportEmitEvents?: boolean;reportOnEvents?: boolean;reservedEvents?: string[];}functionbyteLength(str: string): number{// This is a weird trick, but it works.// Output is the same as TextEncoder.encode(...).lengthreturnunescape(encodeURI(str)).length;}constmethodToRestKeyEmit=(method: FeathersEmitEvents|string)=>{switch(method){case'patch':
case'update': {return'PUT';}case'create': {return'POST';}case'remove': {return'DELETE';}case'get':
case'find':
default: {return'GET';}}};constmethodToRestKeyOn=(method: string)=>{switch(method){case'patched':
case'updated': {return'PUT';}case'created': {return'POST';}case'removed': {return'DELETE';}case'get':
case'find':
default: {return'GET';}}};/* * DataDog metric tracking * Based on @external https://github.com/DataDog/dd-sdk-reactnative/blob/develop/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/XHRProxy.ts */exportconstwatchSocket=(socket: Socket,config: SocketIOInstrumentationConfig={},)=>{const{
reportOnEvents =true,
reportEmitEvents =true,
reservedEvents =[],}=config;if(reportEmitEvents){constoriginalEmit=socket.emit;socket.emit=function(...args: any[]){// ignore reservedEventsif(reservedEvents.includes(args[1])){// @ts-expect-error args is validreturnoriginalEmit.apply(socket,args);}constcontext: RumResourceContext={context: {eventType: 'emit',isSocketIO: true,params: ''},method: methodToRestKeyEmit(args[0]),timer: newTimer(),url: `${BASE_URL}/${args[1]}`,};// captures any extra data and passes it into the context of the payloadif(typeofargs[2]==='string'){context.context.params=JSON.stringify({id: args[2]});}elseif(typeofargs[2]==='object'){context.context.params=JSON.stringify(args[2]);}context.timer.start();letstatusCode=200;letresponseSize=-1;constkey=`${context.timer.startTime}/${context.method}`;rum.startResource(key,context.method,context.url,context.context,context.timer.startTime,);constoriginalCallback=args[args.length-1];constcallback=function(...callbackArgs: any[]){context.timer.stop();// since there can be multiple response arguments, calculate the response size via a reduceresponseSize=callbackArgs.reduce((acc,arg)=>acc+byteLength(JSON.stringify(arg)),0,);// error is passed in as first valueif(callbackArgs[0]){statusCode=callbackArgs[0].code;}rum.stopResource(key,statusCode,'xhr',responseSize,context.context,context.timer.stopTime,);returnoriginalCallback&&typeoforiginalCallback==='function'
? (originalCallback(...callbackArgs)asvoid)
: undefined;};if(originalCallback&&typeoforiginalCallback==='function'){args[args.length-1]=callback;}else{args.push(callback);}// @ts-expect-error args is validreturnoriginalEmit.apply(socket,args);};}if(reportOnEvents){socket.onAny((event: string,data: any)=>{const[service,method]=event.split(' ');conststartTime=Date.now();constmethodKey=methodToRestKeyOn(method);constkey=`${startTime}/${service}/${methodKey}`;consturl=`${BASE_URL}/${service}`;constcontext: RumResourceContext['context']={eventType: 'on',isSocketIO: true,};rum.startResource(key,methodKey,url,context,startTime);rum.stopResource(key,200,'xhr',byteLength(JSON.stringify(data)),context,Date.now(),);});}returnsocket;};
Describe alternatives you've considered
Was able to get this working but it would be great to have this as a first class citizen/RUM feature
Additional context
The text was updated successfully, but these errors were encountered:
angelo-hub
changed the title
Socket.io client support (can also be used for other front-end clients on web
Socket.io client support (can also be used for other front-end clients on web)
Sep 22, 2023
Is your feature request related to a problem? Please describe.
As a user I would like to track socket events similar to how XHR requests are tracked, in our case, we use the feathers-client and this acts as almost a 2 way REST-API
Describe the solution you'd like
Ideally integrating a class that returns a modified version of the Socket.io client that tracks
emit
events, responses and responding.on
eventsWas able to accomplish this ourselves by reworking the XHR requestProxy code, and reviewing openTelemetry's Socket.io instrumentation
Will drop the example code below:
Describe alternatives you've considered
Was able to get this working but it would be great to have this as a first class citizen/RUM feature
Additional context
The text was updated successfully, but these errors were encountered: