Browse Source

feat(contexts): Add Thread Pool Info to Sentry's known contexts (#42284)

Priscila Oliveira 2 years ago
parent
commit
d624aae5d2

+ 3 - 0
static/app/components/events/contexts/chunk.tsx

@@ -100,6 +100,9 @@ class Chunk extends Component<Props, State> {
         return t('Trace Details');
       case 'otel':
         return t('OpenTelemetry');
+      case 'thread_pool_info': // Future new value for thread pool info
+      case 'ThreadPool Info': // Current value for thread pool info
+        return t('Thread Pool Info');
       case 'default':
         if (alias === 'state') {
           return t('Application State');

+ 35 - 0
static/app/components/events/contexts/threadPoolInfo/getThreadPoolInfoKnownDataDetails.spec.tsx

@@ -0,0 +1,35 @@
+import {
+  getThreadPoolInfoKnownDataDetails,
+  threadPoolInfoKnownDataValues,
+} from 'sentry/components/events/contexts/threadPoolInfo/getThreadPoolInfoKnownDataDetails';
+
+import {threadPoolInfoMockData} from './index.spec';
+
+describe('getThreadPoolInfoKnownDataDetails', function () {
+  it('returns values and according to the parameters', function () {
+    const allKnownData: ReturnType<typeof getThreadPoolInfoKnownDataDetails>[] = [];
+
+    for (const type of Object.keys(threadPoolInfoKnownDataValues)) {
+      const threadPoolInfoKnownData = getThreadPoolInfoKnownDataDetails({
+        type: threadPoolInfoKnownDataValues[type],
+        data: threadPoolInfoMockData,
+        event: TestStubs.Event(),
+      });
+
+      if (!threadPoolInfoKnownData) {
+        continue;
+      }
+
+      allKnownData.push(threadPoolInfoKnownData);
+    }
+
+    expect(allKnownData).toEqual([
+      {subject: 'Min Worker Threads', value: 10},
+      {subject: 'Min Completion Port Threads', value: 1},
+      {subject: 'Max Worker Threads', value: 32767},
+      {subject: 'Max Completion Port Threads', value: 1000},
+      {subject: 'Available Worker Threads', value: 32766},
+      {subject: 'Available Completion Port Threads', value: 1000},
+    ]);
+  });
+});

+ 56 - 0
static/app/components/events/contexts/threadPoolInfo/getThreadPoolInfoKnownDataDetails.tsx

@@ -0,0 +1,56 @@
+import {t} from 'sentry/locale';
+import {Event, ThreadPoolInfoContext, ThreadPoolInfoContextKey} from 'sentry/types/event';
+
+export const threadPoolInfoKnownDataValues = Object.values(ThreadPoolInfoContextKey);
+
+type Output = {
+  subject: string;
+  value: React.ReactNode | null;
+};
+
+type Props = {
+  data: ThreadPoolInfoContext;
+  event: Event;
+  type: keyof typeof threadPoolInfoKnownDataValues;
+};
+
+export function getThreadPoolInfoKnownDataDetails({
+  data,
+  type,
+}: Props): Output | undefined {
+  switch (type) {
+    case ThreadPoolInfoContextKey.AVAILABLE_COMPLETION_PORT_THREADS:
+      return {
+        subject: t('Available Completion Port Threads'),
+        value: data.available_completion_port_threads,
+      };
+    case ThreadPoolInfoContextKey.AVAILABLE_WORKER_THREADS:
+      return {
+        subject: t('Available Worker Threads'),
+        value: data.available_worker_threads,
+      };
+
+    case ThreadPoolInfoContextKey.MAX_COMPLETION_PORT_THREADS:
+      return {
+        subject: t('Max Completion Port Threads'),
+        value: data.max_completion_port_threads,
+      };
+    case ThreadPoolInfoContextKey.MAX_WORKER_THREADS:
+      return {
+        subject: t('Max Worker Threads'),
+        value: data.max_worker_threads,
+      };
+    case ThreadPoolInfoContextKey.MIN_COMPLETION_PORT_THREADS:
+      return {
+        subject: t('Min Completion Port Threads'),
+        value: data.min_completion_port_threads,
+      };
+    case ThreadPoolInfoContextKey.MIN_WORKER_THREADS:
+      return {
+        subject: t('Min Worker Threads'),
+        value: data.min_worker_threads,
+      };
+    default:
+      return undefined;
+  }
+}

+ 36 - 0
static/app/components/events/contexts/threadPoolInfo/index.spec.tsx

@@ -0,0 +1,36 @@
+import {render, screen} from 'sentry-test/reactTestingLibrary';
+
+import {ThreadPoolInfoEventContext} from 'sentry/components/events/contexts/threadPoolInfo';
+import {ThreadPoolInfoContext} from 'sentry/types';
+
+export const threadPoolInfoMockData: ThreadPoolInfoContext = {
+  available_completion_port_threads: 1000,
+  available_worker_threads: 32766,
+  max_completion_port_threads: 1000,
+  max_worker_threads: 32767,
+  min_completion_port_threads: 1,
+  min_worker_threads: 10,
+  type: 'threadpool_info',
+};
+
+export const threadPoolInfoMetaMockData = {
+  '': {
+    rem: [['organization:0', 'x']],
+  },
+};
+
+const event = {
+  ...TestStubs.Event(),
+  _meta: {
+    contexts: {
+      threadpool_info: threadPoolInfoMetaMockData,
+    },
+  },
+};
+
+describe('thread pool info event context', function () {
+  it('display redacted data', function () {
+    render(<ThreadPoolInfoEventContext event={event} data={null} />);
+    expect(screen.queryByText('Thread Pool Info')).not.toBeInTheDocument();
+  });
+});

+ 50 - 0
static/app/components/events/contexts/threadPoolInfo/index.tsx

@@ -0,0 +1,50 @@
+import {Fragment} from 'react';
+
+import ContextBlock from 'sentry/components/events/contexts/contextBlock';
+import {Event, ThreadPoolInfoContext} from 'sentry/types/event';
+
+import {geKnownData, getUnknownData} from '../utils';
+
+import {
+  getThreadPoolInfoKnownDataDetails,
+  threadPoolInfoKnownDataValues,
+} from './getThreadPoolInfoKnownDataDetails';
+
+type Props = {
+  data: ThreadPoolInfoContext | null;
+  event: Event;
+};
+
+export function ThreadPoolInfoEventContext({data, event}: Props) {
+  if (!data) {
+    return null;
+  }
+
+  const meta =
+    event._meta?.contexts?.['ThreadPool Info'] ??
+    event._meta?.contexts?.threadpool_info ??
+    {};
+
+  return (
+    <Fragment>
+      <ContextBlock
+        data={geKnownData<
+          ThreadPoolInfoContext,
+          keyof typeof threadPoolInfoKnownDataValues
+        >({
+          data,
+          meta,
+          knownDataTypes: threadPoolInfoKnownDataValues,
+          onGetKnownDataDetails: v => getThreadPoolInfoKnownDataDetails({...v, event}),
+        })}
+      />
+      <ContextBlock
+        data={getUnknownData({
+          allData: data,
+          knownKeys: threadPoolInfoKnownDataValues,
+          meta,
+        })}
+      />
+    </Fragment>
+  );
+}

+ 6 - 0
static/app/components/events/contexts/utils.tsx

@@ -21,6 +21,12 @@ const CONTEXT_TYPES = {
   user: require('sentry/components/events/contexts/user').UserEventContext,
   gpu: require('sentry/components/events/contexts/gpu').GPUEventContext,
   trace: require('sentry/components/events/contexts/trace').TraceEventContext,
+  // 'ThreadPool Info' will be replaced with 'threadpool_info' but
+  // we want to keep it here for now so it works for existing versions
+  'ThreadPool Info': require('sentry/components/events/contexts/threadPoolInfo')
+    .ThreadPoolInfoEventContext,
+  threadpool_info: require('sentry/components/events/contexts/threadPoolInfo')
+    .ThreadPoolInfoEventContext,
   // 'redux.state' will be replaced with more generic context called 'state'
   'redux.state': require('sentry/components/events/contexts/redux').default,
   state: require('sentry/components/events/contexts/state').StateEventContext,

+ 23 - 0
static/app/types/event.tsx

@@ -493,7 +493,29 @@ interface OtelContext extends Partial<Record<OtelContextKey, unknown>>, BaseCont
   [OtelContextKey.RESOURCE]?: Record<string, unknown>;
 }
 
+export enum ThreadPoolInfoContextKey {
+  MIN_WORKER_THREADS = 'min_worker_threads',
+  MIN_COMPLETION_PORT_THREADS = 'min_completion_port_threads',
+  MAX_WORKER_THREADS = 'max_worker_threads',
+  MAX_COMPLETION_PORT_THREADS = 'max_completion_port_threads',
+  AVAILABLE_WORKER_THREADS = 'available_worker_threads',
+  AVAILABLE_COMPLETION_PORT_THREADS = 'available_completion_port_threads',
+}
+
+// ThreadPoolInfo Context
+// TODO(Priscila): Add this context to the docs
+export interface ThreadPoolInfoContext {
+  type: 'ThreadPool Info' | 'threadpool_info';
+  [ThreadPoolInfoContextKey.MIN_WORKER_THREADS]: number;
+  [ThreadPoolInfoContextKey.MIN_COMPLETION_PORT_THREADS]: number;
+  [ThreadPoolInfoContextKey.MAX_WORKER_THREADS]: number;
+  [ThreadPoolInfoContextKey.MAX_COMPLETION_PORT_THREADS]: number;
+  [ThreadPoolInfoContextKey.AVAILABLE_WORKER_THREADS]: number;
+  [ThreadPoolInfoContextKey.AVAILABLE_COMPLETION_PORT_THREADS]: number;
+}
+
 type EventContexts = {
+  'ThreadPool Info'?: ThreadPoolInfoContext;
   client_os?: OSContext;
   device?: DeviceContext;
   feedback?: Record<string, any>;
@@ -503,6 +525,7 @@ type EventContexts = {
   // once perf issue data shape is more clear
   performance_issue?: any;
   runtime?: RuntimeContext;
+  threadpool_info?: ThreadPoolInfoContext;
   trace?: TraceContextType;
 };