Wire up components to Metrics List Index
What does this MR do and why?
Hooking up missing components to the Metrics List UI
- Add
ProvisionedObservabilityContainer
- Add
MetricsList
Closes gitlab-org/opstrace/opstrace#2437 (closed) , gitlab-org/opstrace/opstrace#2470 (closed)
Screenshots or screen recordings
How to set up and validate locally
- Enable
:observability_metrics
feature flag
Apply patch to load mocks
diff --git a/app/assets/javascripts/observability/client.js b/app/assets/javascripts/observability/client.js
index 2f25184e9d6b..491454fa90ec 100644
--- a/app/assets/javascripts/observability/client.js
+++ b/app/assets/javascripts/observability/client.js
@@ -1,18 +1,27 @@
import * as Sentry from '~/sentry/sentry_browser_wrapper';
import axios from '~/lib/utils/axios_utils';
+// import mockData from './mock_traces.json';
function reportErrorAndThrow(e) {
Sentry.captureException(e);
throw e;
}
+
+function mockReturnDataWithDelay(data) {
+ return new Promise((resolve) => {
+ setTimeout(() => resolve(data), 500);
+ });
+}
+
// Provisioning API spec: https://gitlab.com/gitlab-org/opstrace/opstrace/-/blob/main/provisioning-api/pkg/provisioningapi/routes.go#L59
async function enableObservability(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,
- });
+ // return await axios(provisioningUrl, {
+ // method: 'put',
+ // withCredentials: true,
+ // });
+ return mockReturnDataWithDelay();
} catch (e) {
return reportErrorAndThrow(e);
}
@@ -21,19 +30,20 @@ async function enableObservability(provisioningUrl) {
// Provisioning API spec: https://gitlab.com/gitlab-org/opstrace/opstrace/-/blob/main/provisioning-api/pkg/provisioningapi/routes.go#L37
async function isObservabilityEnabled(provisioningUrl) {
try {
- const { data } = await axios.get(provisioningUrl, { withCredentials: true });
+ // const { data } = await axios.get(provisioningUrl, { withCredentials: true });
+ const data = { xstatus: '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 https://gitlab.com/gitlab-org/opstrace/opstrace/-/issues/2315
- return true;
+ return mockReturnDataWithDelay(true);
}
+ return false;
} catch (e) {
if (e.response.status === 404) {
return false;
}
return reportErrorAndThrow(e);
}
- return reportErrorAndThrow(new Error('Failed to check provisioning')); // eslint-disable-line @gitlab/require-i18n-strings
}
async function fetchTrace(tracingUrl, traceId) {
@@ -42,18 +52,19 @@ 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
}
- return data.traces[0];
+ return mockReturnDataWithDelay(data.traces[0]);
} catch (e) {
return reportErrorAndThrow(e);
}
@@ -176,14 +187,15 @@ 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 mockReturnDataWithDelay(data);
} catch (e) {
return reportErrorAndThrow(e);
}
@@ -191,15 +203,20 @@ 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
}
- return data.services;
+ return mockReturnDataWithDelay(data.services);
} catch (e) {
return reportErrorAndThrow(e);
}
@@ -214,15 +231,24 @@ 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
}
- return data.operations;
+ return mockReturnDataWithDelay(data.operations);
} catch (e) {
return reportErrorAndThrow(e);
}
diff --git a/app/assets/javascripts/observability/components/observability_container.vue b/app/assets/javascripts/observability/components/observability_container.vue
index 3027f01ea1e7..1d562d6f087b 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 https://gitlab.com/gitlab-org/opstrace/opstrace/-/issues/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.
-
I have evaluated the MR acceptance checklist for this MR.
Edited by Daniele Rossetti