Skip to content
Snippets Groups Projects

Add InfiniteScrolling and pagination to Observability Logs

Merged Daniele Rossetti requested to merge drosse/logs-pagination into master
All threads resolved!

What does this MR do and why?

Add InfiniteScrolling and pagination to Observability Logs

Closes Add pagination to Logs UI (gitlab-org/opstrace/opstrace#2665 - closed)

MR acceptance checklist

Please evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Screenshots or screen recordings

Screen_Recording_2024-02-22_at_12.39.49

How to set up and validate locally

  • Prerequisites: be logged in and running GDK with Ultimate license
  • Enable :observability_logs feature flag

Apply patch to load mocks ( copy the patch content below and run in your terminal: pbpaste | git apply --allow-empty )

diff --git a/app/assets/javascripts/observability/client.js b/app/assets/javascripts/observability/client.js
index 10613a48ea56..1d158c346f18 100644
--- a/app/assets/javascripts/observability/client.js
+++ b/app/assets/javascripts/observability/client.js
@@ -1,3 +1,4 @@
+/* eslint-disable @gitlab/require-i18n-strings */
 import { isValidDate } from '~/lib/utils/datetime_utility';
 import * as Sentry from '~/sentry/sentry_browser_wrapper';
 import axios from '~/lib/utils/axios_utils';
@@ -9,14 +10,18 @@ function reportErrorAndThrow(e) {
   Sentry.captureException(e);
   throw e;
 }
+
+function mockReturnDataWithDelay(data) {
+  return new Promise((resolve) => {
+    setTimeout(() => resolve(data), 1000);
+  });
+}
+
 // 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,
-    });
+    console.log('[DEBUG] Enabling Observability');
+    return mockReturnDataWithDelay();
   } catch (e) {
     return reportErrorAndThrow(e);
   }
@@ -25,11 +30,12 @@ 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 });
+    console.log('[DEBUG] Checking Observability Enabled');
+    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 https://gitlab.com/gitlab-org/opstrace/opstrace/-/issues/2315
-      return true;
+      return mockReturnDataWithDelay(true);
     }
   } catch (e) {
     if (e.response.status === 404) {
@@ -456,16 +462,157 @@ export async function fetchLogs(logsSearchUrl, { pageToken, pageSize } = {}) {
       params.append('page_size', pageSize);
     }
 
-    const { data } = await axios.get(logsSearchUrl, {
-      withCredentials: true,
-      params,
-    });
-    if (!Array.isArray(data.results)) {
-      throw new Error('logs are missing/invalid in the response'); // eslint-disable-line @gitlab/require-i18n-strings
-    }
+    console.log(`[DEBUG] Fetching logs with params: ${params.toString()}`);
+
+    const data = [
+      {
+        timestamp: '2024-02-19T16:10:15.4433398Z',
+        trace_id: ']?4ft^T\u0011\ufffd\u0013\ufffd6\ufffdbj\ufffd',
+        span_id: "'\u0013\ufffd\ufffd_\ufffd\ufffd\ufffd",
+        trace_flags: 1,
+        severity_text: 'Information',
+        severity_number: 9,
+        service_name: 'cartservice',
+        body:
+          'AddItemAsync called with userId={userId}, productId={productId}, quantity={quantity} AddItemAsync called with userId={userId}, productId={productId}, quantity={quantity} AddItemAsync called with userId={userId}, productId={productId}, quantity={quantity} AddItemAsync called with userId={userId}, productId={productId}, quantity={quantity} AddItemAsync called with userId={userId}, productId={productId}, quantity={quantity} AddItemAsync called with userId={userId}, productId={productId}, quantity={quantity} ',
+        resource_attributes: {
+          'container.id': 'ae165f3300bf7da7cc83b360e955683f31f959268241895747f23ad165014005',
+          'k8s.deployment.name': 'otel-demo-cartservice',
+          'k8s.namespace.name': 'otel-demo-app',
+          'k8s.node.name': 'opstrace-worker2',
+          'k8s.pod.ip': '192.168.62.215',
+          'k8s.pod.name': 'otel-demo-cartservice-6dcc867f5f-pcm68',
+          'k8s.pod.start_time': '2024-02-12T13:32:12Z',
+          'k8s.pod.uid': 'bb0991d5-d2f9-486d-aed6-fb431da28bcb',
+          'service.name': 'cartservice',
+          'service.namespace': 'opentelemetry-demo',
+          'telemetry.sdk.language': 'dotnet',
+          'telemetry.sdk.name': 'opentelemetry',
+          'telemetry.sdk.version': '1.6.0',
+        },
+        log_attributes: {
+          productId: 'LS4PSXUNUM',
+          quantity: '5',
+          userId: '5e22f0f6-cf41-11ee-a97f-768346730ebf',
+        },
+      },
+      {
+        timestamp: '2024-02-19T16:10:15.4488072Z',
+        trace_id: ']?4ft^T\u0011\ufffd\u0013\ufffd6\ufffdbj\ufffd',
+        span_id: '\u0015_\ufffd z\ufffd\ufffd\ufffd',
+        trace_flags: 1,
+        severity_text: 'Information',
+        severity_number: 9,
+        service_name: 'cartservice',
+        body: 'GetCartAsync called with userId={userId}',
+        resource_attributes: {
+          'container.id': 'ae165f3300bf7da7cc83b360e955683f31f959268241895747f23ad165014005',
+          'k8s.deployment.name': 'otel-demo-cartservice',
+          'k8s.namespace.name': 'otel-demo-app',
+          'k8s.node.name': 'opstrace-worker2',
+          'k8s.pod.ip': '192.168.62.215',
+          'k8s.pod.name': 'otel-demo-cartservice-6dcc867f5f-pcm68',
+          'k8s.pod.start_time': '2024-02-12T13:32:12Z',
+          'k8s.pod.uid': 'bb0991d5-d2f9-486d-aed6-fb431da28bcb',
+          'service.name': 'cartservice',
+          'service.namespace': 'opentelemetry-demo',
+          'telemetry.sdk.language': 'dotnet',
+          'telemetry.sdk.name': 'opentelemetry',
+          'telemetry.sdk.version': '1.6.0',
+        },
+        log_attributes: { userId: '5e22f0f6-cf41-11ee-a97f-768346730ebf' },
+      },
+      {
+        timestamp: '2024-02-19T16:10:18.9380111Z',
+        trace_id: '\ufffd\u000cbi\ufffd\u001c\ufffd\ufffd,4f\ufffd!\ufffd\ufffd\ufffd',
+        span_id: '\ufffdv\ufffd(\ufffdyD\ufffd',
+        trace_flags: 1,
+        severity_text: 'Information',
+        severity_number: 9,
+        service_name: 'cartservice',
+        body: 'GetCartAsync called with userId={userId}',
+        resource_attributes: {
+          'container.id': 'ae165f3300bf7da7cc83b360e955683f31f959268241895747f23ad165014005',
+          'k8s.deployment.name': 'otel-demo-cartservice',
+          'k8s.namespace.name': 'otel-demo-app',
+          'k8s.node.name': 'opstrace-worker2',
+          'k8s.pod.ip': '192.168.62.215',
+          'k8s.pod.name': 'otel-demo-cartservice-6dcc867f5f-pcm68',
+          'k8s.pod.start_time': '2024-02-12T13:32:12Z',
+          'k8s.pod.uid': 'bb0991d5-d2f9-486d-aed6-fb431da28bcb',
+          'service.name': 'cartservice',
+          'service.namespace': 'opentelemetry-demo',
+          'telemetry.sdk.language': 'dotnet',
+          'telemetry.sdk.name': 'opentelemetry',
+          'telemetry.sdk.version': '1.6.0',
+        },
+        log_attributes: { userId: '' },
+      },
+      {
+        timestamp: '2024-02-19T16:10:19.7969402Z',
+        trace_id: '\ufffdq\ufffd7\ufffd\ufffd\ufffd\ufffd ]2M~7{\ufffd',
+        span_id: '\u0018H\ufffd\ufffd\ufffd.L\ufffd',
+        trace_flags: 1,
+        severity_text: 'Information',
+        severity_number: 9,
+        service_name: 'cartservice',
+        body:
+          'AddItemAsync called with userId={userId}, productId={productId}, quantity={quantity}',
+        resource_attributes: {
+          'container.id': 'ae165f3300bf7da7cc83b360e955683f31f959268241895747f23ad165014005',
+          'k8s.deployment.name': 'otel-demo-cartservice',
+          'k8s.namespace.name': 'otel-demo-app',
+          'k8s.node.name': 'opstrace-worker2',
+          'k8s.pod.ip': '192.168.62.215',
+          'k8s.pod.name': 'otel-demo-cartservice-6dcc867f5f-pcm68',
+          'k8s.pod.start_time': '2024-02-12T13:32:12Z',
+          'k8s.pod.uid': 'bb0991d5-d2f9-486d-aed6-fb431da28bcb',
+          'service.name': 'cartservice',
+          'service.namespace': 'opentelemetry-demo',
+          'telemetry.sdk.language': 'dotnet',
+          'telemetry.sdk.name': 'opentelemetry',
+          'telemetry.sdk.version': '1.6.0',
+        },
+        log_attributes: {
+          productId: '66VCHSJNUP',
+          quantity: '1',
+          userId: '60bc5708-cf41-11ee-a97f-768346730ebf',
+        },
+      },
+      {
+        timestamp: '2024-02-19T16:10:19.8003226Z',
+        trace_id: '\ufffdq\ufffd7\ufffd\ufffd\ufffd\ufffd ]2M~7{\ufffd',
+        span_id: 'G\u0006\ufffd`B\r\ufffd\ufffd',
+        trace_flags: 1,
+        severity_text: 'Information',
+        severity_number: 9,
+        service_name: 'cartservice',
+        body: 'GetCartAsync called with userId={userId}',
+        resource_attributes: {
+          'container.id': 'ae165f3300bf7da7cc83b360e955683f31f959268241895747f23ad165014005',
+          'k8s.deployment.name': 'otel-demo-cartservice',
+          'k8s.namespace.name': 'otel-demo-app',
+          'k8s.node.name': 'opstrace-worker2',
+          'k8s.pod.ip': '192.168.62.215',
+          'k8s.pod.name': 'otel-demo-cartservice-6dcc867f5f-pcm68',
+          'k8s.pod.start_time': '2024-02-12T13:32:12Z',
+          'k8s.pod.uid': 'bb0991d5-d2f9-486d-aed6-fb431da28bcb',
+          'service.name': 'cartservice',
+          'service.namespace': 'opentelemetry-demo',
+          'telemetry.sdk.language': 'dotnet',
+          'telemetry.sdk.name': 'opentelemetry',
+          'telemetry.sdk.version': '1.6.0',
+        },
+        log_attributes: { userId: '60bc5708-cf41-11ee-a97f-768346730ebf' },
+      },
+    ].map((l) => ({
+      ...l,
+      fingerprint: crypto.randomUUID(),
+    }));
+
     return {
-      logs: data.results,
-      nextPageToken: data.next_page_token,
+      logs: data,
+      nextPageToken: 'test-token',
     };
   } 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 b89c2624f81c..f6cbf7ee771f 100644
--- a/app/assets/javascripts/observability/components/observability_container.vue
+++ b/app/assets/javascripts/observability/components/observability_container.vue
@@ -27,12 +27,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.apiConfig.oauthUrl).origin,
+      });
+    }, 2000);
   },
   destroyed() {
     window.removeEventListener('message', this.messageHandler);
Edited by Daniele Rossetti

Merge request reports

Loading
Loading

Activity

Filter activity
  • Approvals
  • Assignees & reviewers
  • Comments (from bots)
  • Comments (from users)
  • Commits & branches
  • Edits
  • Labels
  • Lock status
  • Mentions
  • Merge request status
  • Tracking
  • Zack Cuddy
  • Zack Cuddy
  • Zack Cuddy
  • Zack Cuddy
  • Zack Cuddy
  • Zack Cuddy
  • Zack Cuddy removed review request for @zcuddy

    removed review request for @zcuddy

  • Daniele Rossetti requested review from @zcuddy

    requested review from @zcuddy

  • added 1 commit

    • 3d0dd1f1 - Fix localisation for infinite-scroll legend

    Compare with previous version

  • Daniele Rossetti added 236 commits

    added 236 commits

    • 3d0dd1f1...13a64258 - 232 commits from branch master
    • 032383f9 - Add support for logs pagination to observability client
    • 919a678f - Add infinity-scrolling and pagination to LogsList
    • 438123d4 - Fix localisation for infinite-scroll legend
    • 0aae43e8 - Fix list horizontal margin

    Compare with previous version

  • Author Developer

    Rebased to fix merging conflicts

  • Zack Cuddy removed review request for @zcuddy

    removed review request for @zcuddy

  • added 1 commit

    Compare with previous version

  • Daniele Rossetti requested review from @zcuddy

    requested review from @zcuddy

  • Daniele Rossetti mentioned in merge request !145839 (merged)

    mentioned in merge request !145839 (merged)

  • Zack Cuddy resolved all threads

    resolved all threads

  • Zack Cuddy approved this merge request

    approved this merge request

  • Zack Cuddy enabled an automatic merge when the pipeline for eebe2b17 succeeds

    enabled an automatic merge when the pipeline for eebe2b17 succeeds

  • Zack Cuddy canceled the automatic merge

    canceled the automatic merge

  • Zack Cuddy enabled an automatic merge when the pipeline for 8e27ba85 succeeds

    enabled an automatic merge when the pipeline for 8e27ba85 succeeds

  • merged

  • Zack Cuddy mentioned in commit cdd7f37f

    mentioned in commit cdd7f37f

  • added workflowstaging label and removed workflowcanary label

  • Please register or sign in to reply
    Loading