Skip to content

Tracing - Add operations suggestions to filter bar

Daniele Rossetti requested to merge rossetd/filter-suggestions-pt2 into master

What does this MR do and why?

  • Add ServiceToken - responsible for fetching list of services suggestions

    • Note the API does not support searchTerm so this is currently handled on the client
    • Also note services suggestions are not currently preloaded. Might add it separately.
  • Add OperationsToken - responsible for fetching list of operations suggestions, based on the selected service

    • Note the API does not support searchTerm so this is currently handled on the client
    • If no services are selected, it shows a message indicating that suggestions need a service to be selected
    • If multiple services are selected, it fetches multiple suggestions and merge them
  • Prerequisite MR: !133849 (merged)

  • Closes gitlab-org/opstrace/opstrace#2369+

Screenshots or screen recordings

image image image

How to set up and validate locally

  • Enable :observability_tracing FF
Apply patch to load mocks diff --git a/app/assets/javascripts/observability/client.js b/app/assets/javascripts/observability/client.js index d62c02c9a132..39ca396bdd24 100644 --- a/app/assets/javascripts/observability/client.js +++ b/app/assets/javascripts/observability/client.js @@ -1,5 +1,6 @@ import * as Sentry from '@sentry/browser'; import axios from '~/lib/utils/axios_utils'; +import mockData from './mock_traces.json';

function reportErrorAndThrow(e) { Sentry.captureException(e); @@ -9,10 +10,11 @@ function reportErrorAndThrow(e) { async function enableTraces(provisioningUrl) { try { // Note: axios.put(url, undefined, {withCredentials: true}) does not send cookies properly, so need to use the API below for the correct behaviour

  • return await axios(provisioningUrl, {
  •  method: 'put',
  •  withCredentials: true,
  • });
  • const { data } = await axios.get(provisioningUrl, { withCredentials: true });
  • // const { data } = await axios.get(provisioningUrl, { withCredentials: true });
  • const data = { status: 'ready' };
  • if (data && data.status) { // we currently ignore the 'status' payload and just check if the request was successful // We might improve this as part of gitlab-org/opstrace/opstrace#2315 @@ -42,12 +46,13 @@ async function fetchTrace(tracingUrl, traceId) { throw new Error('traceId is required.'); }
  • const { data } = await axios.get(tracingUrl, {
  •  withCredentials: true,
  •  params: {
  •    trace_id: traceId,
  •  },
  • });
  • // const { data } = await axios.get(tracingUrl, {

  • // withCredentials: true,

  • // params: {

  • // trace_id: traceId,

  • // },

  • // });

  • const data = { traces: [mockData.traces.find((t) => t.trace_id === traceId)] };

    if (!Array.isArray(data.traces) || data.traces.length === 0) { throw new Error('traces are missing/invalid in the response'); // eslint-disable-line @gitlab/require-i18n-strings @@ -176,14 +181,16 @@ async function fetchTraces(tracingUrl, { filters = {}, pageToken, pageSize } = { }

try {

  • const { data } = await axios.get(tracingUrl, {
  •  withCredentials: true,
  •  params,
  • });
  • // const { data } = await axios.get(tracingUrl, {
  • // withCredentials: true,
  • // params,
  • // });
  • const data = mockData; if (!Array.isArray(data.traces)) { throw new Error('traces are missing/invalid in the response'); // eslint-disable-line @gitlab/require-i18n-strings } return data;
  • // return { traces: [] }; } catch (e) { return reportErrorAndThrow(e); } @@ -191,9 +198,14 @@ async function fetchTraces(tracingUrl, { filters = {}, pageToken, pageSize } = {

async function fetchServices(servicesUrl) { try {

  • const { data } = await axios.get(servicesUrl, {
  •  withCredentials: true,
  • });
  • // const { data } = await axios.get(servicesUrl, {

  • // withCredentials: true,

  • // });

  • const uniqueServices = new Set(

  •  mockData.traces.map((t) => t.spans.map((s) => s.service_name)).flat(),
  • );

  • const data = { services: Array.from(uniqueServices).map((s) => ({ name: s })) };

    if (!Array.isArray(data.services)) { throw new Error('failed to fetch services. invalid response'); // eslint-disable-line @gitlab/require-i18n-strings @@ -214,9 +226,18 @@ async function fetchOperations(operationsUrl, serviceName) { throw new Error('fetchOperations() - operationsUrl must contain SERVICE_NAME'); } const url = operationsUrl.replace('SERVICE_NAME', serviceName);

  • const { data } = await axios.get(url, {
  •  withCredentials: true,
  • });
  • // const { data } = await axios.get(url, {

  • // withCredentials: true,

  • // });

  • console.log('fetching operations suggestions for', url); // eslint-disable-line @gitlab/require-i18n-strings

  • const uniqOps = new Set(

  •  mockData.traces
  •    .map((t) => t.spans.filter((s) => s.service_name === serviceName))
  •    .flat()
  •    .map((s) => s.operation),
  • );

  • const data = { operations: Array.from(uniqOps).map((s) => ({ name: s })) };

    if (!Array.isArray(data.operations)) { throw new Error('failed to fetch operations. invalid response'); // eslint-disable-line @gitlab/require-i18n-strings diff --git a/app/assets/javascripts/observability/components/observability_container.vue b/app/assets/javascripts/observability/components/observability_container.vue index 1518c1325601..0fb8bf3dc651 100644 --- a/app/assets/javascripts/observability/components/observability_container.vue +++ b/app/assets/javascripts/observability/components/observability_container.vue @@ -41,12 +41,12 @@ export default {

    // TODO: Improve local GDK dev experience with tracing gitlab-org/opstrace/opstrace#2308 // Uncomment the lines below to to test this locally

  • // setTimeout(() => {
  • // this.messageHandler({
  • // data: { type: 'AUTH_COMPLETION', status: 'success' },
  • // origin: new URL(this.oauthUrl).origin,
  • // });
  • // }, 2000);
  • setTimeout(() => {
  •  this.messageHandler({
  •    data: { type: 'AUTH_COMPLETION', status: 'success' },
  •    origin: new URL(this.oauthUrl).origin,
  •  });
  • }, 2000); }, destroyed() { window.removeEventListener('message', this.messageHandler);

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Daniele Rossetti

Merge request reports