@localstack/appinspector-ui 1.0.0-dev-dc58bc41 → 1.0.0-dev-f55daae2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/pages/spans-list-page.tsx
2
- import { Box as Box5 } from "@mui/material";
3
- import { useCallback as useCallback3, useEffect as useEffect2, useRef as useRef2, useState as useState3 } from "react";
2
+ import { Box as Box6 } from "@mui/material";
3
+ import { useCallback as useCallback4, useEffect as useEffect3, useRef as useRef3, useState as useState4 } from "react";
4
4
  import { useNavigate } from "react-router-dom";
5
5
 
6
6
  // src/api/use-api.tsx
@@ -108,7 +108,7 @@ function unixNanoToDate(unixNanoString) {
108
108
 
109
109
  // src/components/cells/responsive-timestamp-cell.tsx
110
110
  import { jsx as jsx2 } from "react/jsx-runtime";
111
- var ResponsiveTimestampCell = ({ value }) => {
111
+ var ResponsiveTimestampCell = ({ locale, value }) => {
112
112
  const [columnWidth, setColumnWidth] = useState(0);
113
113
  const cellReference = useRef(null);
114
114
  useEffect(() => {
@@ -134,35 +134,41 @@ var ResponsiveTimestampCell = ({ value }) => {
134
134
  const date = unixNanoToDate(value);
135
135
  if (!date) return;
136
136
  if (columnWidth < 100) {
137
- return date.toLocaleTimeString(void 0, {
137
+ const formatter = new Intl.DateTimeFormat(locale, {
138
138
  hour: "2-digit",
139
139
  hour12: false,
140
140
  minute: "2-digit",
141
141
  second: "2-digit"
142
142
  });
143
+ return formatter.format(date);
143
144
  } else if (columnWidth < 160) {
144
- const timeString = date.toLocaleTimeString(void 0, {
145
+ const formatter = new Intl.DateTimeFormat(locale, {
145
146
  hour: "2-digit",
146
147
  hour12: false,
147
148
  minute: "2-digit",
148
149
  second: "2-digit"
149
150
  });
151
+ const timeString = formatter.format(date);
150
152
  const ms = date.getMilliseconds().toString().padStart(3, "0");
151
153
  return `${timeString}:${ms}`;
152
154
  } else {
153
- const day = date.getDate().toString().padStart(2, "0");
154
- const month = (date.getMonth() + 1).toString().padStart(2, "0");
155
- const year = date.getFullYear().toString();
156
- const timeString = date.toLocaleTimeString(void 0, {
155
+ const dateFormatter = new Intl.DateTimeFormat(locale, {
156
+ day: "2-digit",
157
+ month: "2-digit",
158
+ year: "numeric"
159
+ });
160
+ const timeFormatter = new Intl.DateTimeFormat(locale, {
157
161
  hour: "2-digit",
158
162
  hour12: false,
159
163
  minute: "2-digit",
160
164
  second: "2-digit"
161
165
  });
166
+ const dateString = dateFormatter.format(date);
167
+ const timeString = timeFormatter.format(date);
162
168
  const ms = date.getMilliseconds().toString().padStart(3, "0");
163
- return `${day}.${month}.${year} - ${timeString}:${ms}`;
169
+ return `${dateString} - ${timeString}:${ms}`;
164
170
  }
165
- }, [value, columnWidth]);
171
+ }, [value, columnWidth, locale]);
166
172
  if (!formattedTime) return /* @__PURE__ */ jsx2("span", { children: "N/A" });
167
173
  return /* @__PURE__ */ jsx2("div", { ref: cellReference, style: { width: "100%" }, children: formattedTime });
168
174
  };
@@ -2839,24 +2845,298 @@ var SpansList = (props) => {
2839
2845
  ] });
2840
2846
  };
2841
2847
 
2842
- // src/context.tsx
2843
- import { createContext as createContext2, useContext as useContext2 } from "react";
2844
- import { useCallback as useCallback2, useMemo as useMemo3 } from "react";
2848
+ // src/components/status-message/status-message.tsx
2849
+ import ErrorOutlineIcon from "@mui/icons-material/ErrorOutline";
2850
+ import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined";
2851
+ import { Alert as Alert2, AlertTitle, Box as Box5, Button as Button3, Link, Typography as Typography3 } from "@mui/material";
2852
+
2853
+ // src/api/errors.ts
2854
+ var AppInspectorNotFoundError = class extends Error {
2855
+ constructor(message, cause) {
2856
+ super(message);
2857
+ this.name = "AppInspectorNotFoundError";
2858
+ this.cause = cause;
2859
+ }
2860
+ };
2861
+ var ConnectionError = class extends Error {
2862
+ constructor(message, cause) {
2863
+ super(message);
2864
+ this.name = "ConnectionError";
2865
+ this.cause = cause;
2866
+ }
2867
+ };
2845
2868
 
2846
2869
  // src/config.ts
2847
2870
  var APPINSPECTOR_API_PREFIX = "/_localstack/appinspector";
2848
2871
  var API_VERSION = "v1";
2849
2872
  var API_ENDPOINTS = {
2873
+ ROOT: "/",
2850
2874
  SPANS: "/traces/*/spans",
2875
+ STATUS: "/status",
2851
2876
  TRACES: "/traces"
2852
2877
  };
2853
- var getApiEndpoint = (endpoint) => {
2878
+ var getApiV1Endpoint = (endpoint) => {
2854
2879
  return `/${API_VERSION}${endpoint}`;
2855
2880
  };
2881
+ var getApiEndpoint = (endpoint) => {
2882
+ if (endpoint === API_ENDPOINTS.ROOT || endpoint === API_ENDPOINTS.STATUS) {
2883
+ return endpoint;
2884
+ }
2885
+ return getApiV1Endpoint(endpoint);
2886
+ };
2856
2887
  var getAppInspectorApiUrl = (localstackEndpoint, endpoint) => {
2857
2888
  return `${localstackEndpoint}${APPINSPECTOR_API_PREFIX}${getApiEndpoint(endpoint)}`;
2858
2889
  };
2859
2890
 
2891
+ // src/components/status-message/status-message.tsx
2892
+ import { jsx as jsx126, jsxs as jsxs122 } from "react/jsx-runtime";
2893
+ var StatusMessage = ({
2894
+ error,
2895
+ onRetry,
2896
+ status
2897
+ }) => {
2898
+ if (error instanceof AppInspectorNotFoundError) {
2899
+ return /* @__PURE__ */ jsx126(
2900
+ Box5,
2901
+ {
2902
+ sx: {
2903
+ alignItems: "center",
2904
+ display: "flex",
2905
+ flexDirection: "column",
2906
+ gap: 2,
2907
+ justifyContent: "center",
2908
+ p: 4
2909
+ },
2910
+ children: /* @__PURE__ */ jsxs122(
2911
+ Alert2,
2912
+ {
2913
+ icon: /* @__PURE__ */ jsx126(ErrorOutlineIcon, { fontSize: "large" }),
2914
+ severity: "error",
2915
+ sx: { maxWidth: 600, width: "100%" },
2916
+ children: [
2917
+ /* @__PURE__ */ jsx126(AlertTitle, { sx: { fontWeight: "bold" }, children: "App Inspector Not Available" }),
2918
+ /* @__PURE__ */ jsx126(Typography3, { sx: { mb: 2 }, variant: "body2", children: "The App Inspector extension is not licensed or not enabled in LocalStack." }),
2919
+ /* @__PURE__ */ jsx126(Typography3, { sx: { mb: 1 }, variant: "body2", children: /* @__PURE__ */ jsx126("strong", { children: "To enable App Inspector:" }) }),
2920
+ /* @__PURE__ */ jsx126(Typography3, { sx: { mb: 1 }, variant: "body2", children: "Set the environment variable and restart LocalStack:" }),
2921
+ /* @__PURE__ */ jsx126(
2922
+ Box5,
2923
+ {
2924
+ component: "pre",
2925
+ sx: {
2926
+ backgroundColor: "rgba(0, 0, 0, 0.05)",
2927
+ borderRadius: 1,
2928
+ fontSize: "0.875rem",
2929
+ p: 1
2930
+ },
2931
+ children: "APPINSPECTOR=1"
2932
+ }
2933
+ ),
2934
+ /* @__PURE__ */ jsxs122(Typography3, { sx: { fontStyle: "italic", mb: 1, mt: 2 }, variant: "body2", children: [
2935
+ "Runtime changes can be made via endpoint",
2936
+ " ",
2937
+ /* @__PURE__ */ jsxs122("code", { children: [
2938
+ APPINSPECTOR_API_PREFIX,
2939
+ "/status"
2940
+ ] }),
2941
+ ". For persistent default state across restarts, adjust the",
2942
+ /* @__PURE__ */ jsx126("code", { children: "APPINSPECTOR" }),
2943
+ " ",
2944
+ "environment variable."
2945
+ ] }),
2946
+ /* @__PURE__ */ jsx126(Typography3, { sx: { mb: 1, mt: 2 }, variant: "body2", children: /* @__PURE__ */ jsx126("strong", { children: "For more information:" }) }),
2947
+ /* @__PURE__ */ jsx126(
2948
+ Link,
2949
+ {
2950
+ href: "https://docs.localstack.cloud/user-guide/tools/application-inspector/",
2951
+ rel: "noopener noreferrer",
2952
+ target: "_blank",
2953
+ children: "App Inspector Documentation"
2954
+ }
2955
+ ),
2956
+ onRetry && /* @__PURE__ */ jsx126(Box5, { sx: { display: "flex", justifyContent: "flex-start", mt: 2 }, children: /* @__PURE__ */ jsx126(
2957
+ Button3,
2958
+ {
2959
+ "aria-label": "Check App Inspector status again",
2960
+ onClick: onRetry,
2961
+ variant: "outlined",
2962
+ children: "Check Again"
2963
+ }
2964
+ ) })
2965
+ ]
2966
+ }
2967
+ )
2968
+ }
2969
+ );
2970
+ }
2971
+ if (error instanceof ConnectionError) {
2972
+ return /* @__PURE__ */ jsx126(
2973
+ Box5,
2974
+ {
2975
+ sx: {
2976
+ alignItems: "center",
2977
+ display: "flex",
2978
+ flexDirection: "column",
2979
+ gap: 2,
2980
+ justifyContent: "center",
2981
+ p: 4
2982
+ },
2983
+ children: /* @__PURE__ */ jsxs122(
2984
+ Alert2,
2985
+ {
2986
+ icon: /* @__PURE__ */ jsx126(ErrorOutlineIcon, { fontSize: "large" }),
2987
+ severity: "error",
2988
+ sx: { maxWidth: 600, width: "100%" },
2989
+ children: [
2990
+ /* @__PURE__ */ jsx126(AlertTitle, { sx: { fontWeight: "bold" }, children: "Connection Error" }),
2991
+ /* @__PURE__ */ jsx126(Typography3, { sx: { mb: 2 }, variant: "body2", children: "Failed to connect to LocalStack. Please ensure LocalStack is running and accessible." }),
2992
+ /* @__PURE__ */ jsx126(Typography3, { sx: { mb: 1 }, variant: "body2", children: /* @__PURE__ */ jsx126("strong", { children: "To start LocalStack:" }) }),
2993
+ /* @__PURE__ */ jsx126(
2994
+ Box5,
2995
+ {
2996
+ component: "pre",
2997
+ sx: {
2998
+ backgroundColor: "rgba(0, 0, 0, 0.05)",
2999
+ borderRadius: 1,
3000
+ fontSize: "0.875rem",
3001
+ p: 1
3002
+ },
3003
+ children: "localstack start"
3004
+ }
3005
+ ),
3006
+ onRetry && /* @__PURE__ */ jsx126(Box5, { sx: { display: "flex", justifyContent: "flex-start", mt: 2 }, children: /* @__PURE__ */ jsx126(
3007
+ Button3,
3008
+ {
3009
+ "aria-label": "Retry connection to LocalStack",
3010
+ onClick: onRetry,
3011
+ variant: "outlined",
3012
+ children: "Retry Connection"
3013
+ }
3014
+ ) })
3015
+ ]
3016
+ }
3017
+ )
3018
+ }
3019
+ );
3020
+ }
3021
+ if (status?.status === "DISABLED") {
3022
+ return /* @__PURE__ */ jsx126(
3023
+ Box5,
3024
+ {
3025
+ sx: {
3026
+ alignItems: "center",
3027
+ display: "flex",
3028
+ flexDirection: "column",
3029
+ gap: 2,
3030
+ justifyContent: "center",
3031
+ p: 4
3032
+ },
3033
+ children: /* @__PURE__ */ jsxs122(
3034
+ Alert2,
3035
+ {
3036
+ icon: /* @__PURE__ */ jsx126(InfoOutlinedIcon, { fontSize: "large" }),
3037
+ severity: "warning",
3038
+ sx: { maxWidth: 600, width: "100%" },
3039
+ children: [
3040
+ /* @__PURE__ */ jsx126(AlertTitle, { sx: { fontWeight: "bold" }, children: "App Inspector is Disabled" }),
3041
+ /* @__PURE__ */ jsx126(Typography3, { sx: { mb: 2 }, variant: "body2", children: "App Inspector is currently disabled. Please enable it to view traces and spans." }),
3042
+ /* @__PURE__ */ jsx126(Typography3, { sx: { mb: 1 }, variant: "body2", children: /* @__PURE__ */ jsx126("strong", { children: "To enable App Inspector at runtime:" }) }),
3043
+ /* @__PURE__ */ jsx126(
3044
+ Box5,
3045
+ {
3046
+ component: "pre",
3047
+ sx: {
3048
+ backgroundColor: "rgba(0, 0, 0, 0.05)",
3049
+ borderRadius: 1,
3050
+ fontSize: "0.875rem",
3051
+ overflowX: "auto",
3052
+ p: 1
3053
+ },
3054
+ children: `curl -X PUT http://localhost:4566${APPINSPECTOR_API_PREFIX}/status \\
3055
+ -H "Content-Type: application/json" \\
3056
+ -d '{"status": "ENABLED"}'`
3057
+ }
3058
+ ),
3059
+ /* @__PURE__ */ jsx126(Typography3, { sx: { mb: 1, mt: 2 }, variant: "body2", children: /* @__PURE__ */ jsx126("strong", { children: "To enable App Inspector persistently across restarts:" }) }),
3060
+ /* @__PURE__ */ jsx126(Typography3, { sx: { mb: 1 }, variant: "body2", children: "Set the environment variable:" }),
3061
+ /* @__PURE__ */ jsx126(
3062
+ Box5,
3063
+ {
3064
+ component: "pre",
3065
+ sx: {
3066
+ backgroundColor: "rgba(0, 0, 0, 0.05)",
3067
+ borderRadius: 1,
3068
+ fontSize: "0.875rem",
3069
+ p: 1
3070
+ },
3071
+ children: "APPINSPECTOR=1"
3072
+ }
3073
+ ),
3074
+ Boolean(status.note) && /* @__PURE__ */ jsx126(Typography3, { sx: { display: "block", fontStyle: "italic", mt: 2 }, variant: "caption", children: status.note }),
3075
+ onRetry && /* @__PURE__ */ jsx126(Box5, { sx: { display: "flex", justifyContent: "flex-start", mt: 2 }, children: /* @__PURE__ */ jsx126(
3076
+ Button3,
3077
+ {
3078
+ "aria-label": "Check if App Inspector is enabled",
3079
+ onClick: onRetry,
3080
+ variant: "outlined",
3081
+ children: "Check Status Again"
3082
+ }
3083
+ ) })
3084
+ ]
3085
+ }
3086
+ )
3087
+ }
3088
+ );
3089
+ }
3090
+ if (error) {
3091
+ return /* @__PURE__ */ jsx126(
3092
+ Box5,
3093
+ {
3094
+ sx: {
3095
+ alignItems: "center",
3096
+ display: "flex",
3097
+ flexDirection: "column",
3098
+ gap: 2,
3099
+ justifyContent: "center",
3100
+ p: 4
3101
+ },
3102
+ children: /* @__PURE__ */ jsxs122(
3103
+ Alert2,
3104
+ {
3105
+ icon: /* @__PURE__ */ jsx126(ErrorOutlineIcon, { fontSize: "large" }),
3106
+ severity: "error",
3107
+ sx: { maxWidth: 600, width: "100%" },
3108
+ children: [
3109
+ /* @__PURE__ */ jsx126(AlertTitle, { sx: { fontWeight: "bold" }, children: "Error" }),
3110
+ /* @__PURE__ */ jsx126(Typography3, { sx: { mb: 2 }, variant: "body2", children: error.message }),
3111
+ onRetry && /* @__PURE__ */ jsx126(Box5, { sx: { display: "flex", justifyContent: "flex-start", mt: 2 }, children: /* @__PURE__ */ jsx126(
3112
+ Button3,
3113
+ {
3114
+ "aria-label": "Retry operation",
3115
+ onClick: onRetry,
3116
+ variant: "outlined",
3117
+ children: "Retry"
3118
+ }
3119
+ ) })
3120
+ ]
3121
+ }
3122
+ )
3123
+ }
3124
+ );
3125
+ }
3126
+ return;
3127
+ };
3128
+
3129
+ // src/context.tsx
3130
+ import { createContext as createContext2, useContext as useContext2 } from "react";
3131
+ import { useCallback as useCallback2, useMemo as useMemo3 } from "react";
3132
+
3133
+ // src/constants/error-messages.ts
3134
+ var ERROR_MESSAGES = {
3135
+ APP_INSPECTOR_DISABLED: "App Inspector is currently disabled.",
3136
+ APP_INSPECTOR_NOT_FOUND: "App Inspector extension not found. Please ensure App Inspector is licensed and enabled.",
3137
+ CONNECTION_FAILED: "Failed to connect to LocalStack. Please ensure LocalStack is running and accessible."
3138
+ };
3139
+
2860
3140
  // src/api/client.ts
2861
3141
  var apiLogger = createScopedLogger("API");
2862
3142
  var makeRequest = async (options) => {
@@ -2870,10 +3150,23 @@ var makeRequest = async (options) => {
2870
3150
  headers
2871
3151
  });
2872
3152
  if (!response.ok) {
3153
+ if (response.status === 404) {
3154
+ throw new AppInspectorNotFoundError(
3155
+ ERROR_MESSAGES.APP_INSPECTOR_NOT_FOUND,
3156
+ new Error(`404 from ${url}: ${response.statusText}`)
3157
+ );
3158
+ }
2873
3159
  throw new Error(`API request failed: ${response.status.toString()} ${response.statusText}`);
2874
3160
  }
2875
3161
  return await response.json();
2876
3162
  } catch (error) {
3163
+ if (error instanceof TypeError) {
3164
+ const message = error.message.toLowerCase();
3165
+ const isNetworkError = message.includes("fetch") || message.includes("network") || message.includes("failed to fetch");
3166
+ if (isNetworkError) {
3167
+ throw new ConnectionError(ERROR_MESSAGES.CONNECTION_FAILED, error);
3168
+ }
3169
+ }
2877
3170
  if (error instanceof Error) {
2878
3171
  throw error;
2879
3172
  }
@@ -2913,12 +3206,18 @@ var createApiClient = ({ localstackEndpoint }) => {
2913
3206
  getSpans: async (request) => {
2914
3207
  const endpoint = buildSpansEndpoint(request);
2915
3208
  return makeRequest({ endpoint, localstackEndpoint });
3209
+ },
3210
+ getStatus: async () => {
3211
+ return makeRequest({
3212
+ endpoint: API_ENDPOINTS.STATUS,
3213
+ localstackEndpoint
3214
+ });
2916
3215
  }
2917
3216
  };
2918
3217
  };
2919
3218
 
2920
3219
  // src/context.tsx
2921
- import { jsx as jsx126 } from "react/jsx-runtime";
3220
+ import { jsx as jsx127 } from "react/jsx-runtime";
2922
3221
  var AppInspectorContext = createContext2(void 0);
2923
3222
  var useAppInspector = () => {
2924
3223
  const context = useContext2(AppInspectorContext);
@@ -2931,7 +3230,7 @@ var AppInspectorContextProvider = (props) => {
2931
3230
  const api = useMemo3(() => {
2932
3231
  return false ? createApiClientMock() : createApiClient({ localstackEndpoint: props.localstackEndpoint });
2933
3232
  }, [props.localstackEndpoint]);
2934
- return /* @__PURE__ */ jsx126(ApiProvider, { api, children: /* @__PURE__ */ jsx126(
3233
+ return /* @__PURE__ */ jsx127(ApiProvider, { api, children: /* @__PURE__ */ jsx127(
2935
3234
  AppInspectorContext.Provider,
2936
3235
  {
2937
3236
  value: {
@@ -2955,17 +3254,60 @@ var AppInspectorContextProvider = (props) => {
2955
3254
  ) });
2956
3255
  };
2957
3256
 
3257
+ // src/hooks/use-status.tsx
3258
+ import { useCallback as useCallback3, useEffect as useEffect2, useRef as useRef2, useState as useState3 } from "react";
3259
+ var useStatus = () => {
3260
+ const api = useAppInspectorApi();
3261
+ const [checking, setChecking] = useState3(true);
3262
+ const [status, setStatus] = useState3();
3263
+ const [error, setError] = useState3();
3264
+ const hasFetchedReference = useRef2(false);
3265
+ const abortControllerReference = useRef2(null);
3266
+ const checkStatus = useCallback3(async () => {
3267
+ if (abortControllerReference.current) {
3268
+ abortControllerReference.current.abort();
3269
+ }
3270
+ const abortController = new AbortController();
3271
+ abortControllerReference.current = abortController;
3272
+ setChecking(true);
3273
+ try {
3274
+ const response = await api.getStatus();
3275
+ if (!abortController.signal.aborted) {
3276
+ setStatus(response);
3277
+ setError(void 0);
3278
+ }
3279
+ } catch (error_) {
3280
+ if (!abortController.signal.aborted) {
3281
+ setError(error_ instanceof Error ? error_ : new Error("Unknown error"));
3282
+ setStatus(void 0);
3283
+ }
3284
+ } finally {
3285
+ if (!abortController.signal.aborted) {
3286
+ setChecking(false);
3287
+ }
3288
+ }
3289
+ }, [api]);
3290
+ useEffect2(() => {
3291
+ if (!hasFetchedReference.current) {
3292
+ hasFetchedReference.current = true;
3293
+ void checkStatus();
3294
+ }
3295
+ }, [checkStatus]);
3296
+ return { checking, checkStatus, error, status };
3297
+ };
3298
+
2958
3299
  // src/pages/spans-list-page.tsx
2959
- import { jsx as jsx127 } from "react/jsx-runtime";
3300
+ import { jsx as jsx128 } from "react/jsx-runtime";
2960
3301
  var MAX_WIDTH = 1400;
2961
3302
  var SpansListPage = () => {
2962
3303
  const api = useAppInspectorApi();
2963
- const [spans, setSpans] = useState3();
2964
- const [loading, setLoading] = useState3(false);
2965
- const hasFetched = useRef2(false);
2966
- const [filterWriteOperations, setFilterWriteOperations] = useState3(true);
2967
- const [fetchError, setFetchError] = useState3();
2968
- const fetchSpans = useCallback3(async () => {
3304
+ const [spans, setSpans] = useState4();
3305
+ const [loading, setLoading] = useState4(false);
3306
+ const hasFetched = useRef3(false);
3307
+ const [filterWriteOperations, setFilterWriteOperations] = useState4(true);
3308
+ const [fetchError, setFetchError] = useState4();
3309
+ const { checkStatus, error: statusError, status } = useStatus();
3310
+ const fetchSpans = useCallback4(async () => {
2969
3311
  setLoading(true);
2970
3312
  try {
2971
3313
  const response = await api.getSpans({
@@ -2981,25 +3323,26 @@ var SpansListPage = () => {
2981
3323
  setLoading(false);
2982
3324
  }
2983
3325
  }, [api, filterWriteOperations]);
2984
- const fetchSpansSync = useCallback3(() => {
3326
+ const fetchSpansSync = useCallback4(() => {
2985
3327
  void fetchSpans();
2986
3328
  }, [fetchSpans]);
2987
- useEffect2(() => {
3329
+ useEffect3(() => {
2988
3330
  if (hasFetched.current) return;
3331
+ if (status?.status !== "ENABLED") return;
2989
3332
  hasFetched.current = true;
2990
3333
  void fetchSpans();
2991
- }, [fetchSpans]);
2992
- useEffect2(() => {
3334
+ }, [fetchSpans, status]);
3335
+ useEffect3(() => {
2993
3336
  if (!hasFetched.current) return;
2994
3337
  void fetchSpans();
2995
3338
  }, [fetchSpans]);
2996
3339
  const navigate = useNavigate();
2997
3340
  const { resolveLink } = useAppInspector();
2998
- const navigateToSpan = useCallback3((span) => {
3341
+ const navigateToSpan = useCallback4((span) => {
2999
3342
  const url = resolveLink({ to: "trace-graph", traceId: span.trace_id });
3000
3343
  navigate(`${url}?spanId=${span.span_id}`);
3001
3344
  }, [navigate, resolveLink]);
3002
- const clearSpans = useCallback3(async () => {
3345
+ const clearSpans = useCallback4(async () => {
3003
3346
  setLoading(true);
3004
3347
  try {
3005
3348
  await api.deleteSpans();
@@ -3013,8 +3356,12 @@ var SpansListPage = () => {
3013
3356
  setLoading(false);
3014
3357
  }
3015
3358
  }, [api, fetchSpans]);
3016
- return /* @__PURE__ */ jsx127(
3017
- Box5,
3359
+ const handleRetry = useCallback4(() => {
3360
+ void checkStatus();
3361
+ }, [checkStatus]);
3362
+ const shouldShowStatusMessage = Boolean(statusError) || status?.status === "DISABLED";
3363
+ return /* @__PURE__ */ jsx128(
3364
+ Box6,
3018
3365
  {
3019
3366
  "data-testid": "spans-list-page",
3020
3367
  sx: {
@@ -3024,8 +3371,8 @@ var SpansListPage = () => {
3024
3371
  height: "100vh",
3025
3372
  width: "100%"
3026
3373
  },
3027
- children: /* @__PURE__ */ jsx127(
3028
- Box5,
3374
+ children: /* @__PURE__ */ jsx128(
3375
+ Box6,
3029
3376
  {
3030
3377
  sx: {
3031
3378
  display: "flex",
@@ -3034,7 +3381,14 @@ var SpansListPage = () => {
3034
3381
  maxWidth: MAX_WIDTH,
3035
3382
  width: "100%"
3036
3383
  },
3037
- children: /* @__PURE__ */ jsx127(
3384
+ children: shouldShowStatusMessage ? /* @__PURE__ */ jsx128(
3385
+ StatusMessage,
3386
+ {
3387
+ error: statusError,
3388
+ onRetry: handleRetry,
3389
+ status
3390
+ }
3391
+ ) : /* @__PURE__ */ jsx128(
3038
3392
  SpansList,
3039
3393
  {
3040
3394
  filterWriteOperations,
@@ -3064,22 +3418,22 @@ var SpansListPage = () => {
3064
3418
  };
3065
3419
 
3066
3420
  // src/pages/trace-graph.tsx
3067
- import { Box as Box11, Drawer, Paper as Paper2 } from "@mui/material";
3421
+ import { Box as Box12, Drawer, Paper as Paper2 } from "@mui/material";
3068
3422
  import { styled } from "@mui/material/styles";
3069
3423
  import { ReactFlowProvider } from "@xyflow/react";
3070
- import { useCallback as useCallback6, useEffect as useEffect4, useState as useState6 } from "react";
3424
+ import { useCallback as useCallback7, useEffect as useEffect5, useState as useState7 } from "react";
3071
3425
  import { useParams, useSearchParams } from "react-router-dom";
3072
3426
 
3073
3427
  // src/components/event-details/event-details.tsx
3074
- import { Box as Box8, Chip, Divider, Stack, Typography as Typography5 } from "@mui/material";
3428
+ import { Box as Box9, Chip, Divider, Stack, Typography as Typography6 } from "@mui/material";
3075
3429
 
3076
3430
  // src/components/event-details/event-details-header.tsx
3077
3431
  import { Close } from "@mui/icons-material";
3078
- import { Box as Box6, IconButton, Typography as Typography3 } from "@mui/material";
3079
- import { jsx as jsx128, jsxs as jsxs122 } from "react/jsx-runtime";
3432
+ import { Box as Box7, IconButton, Typography as Typography4 } from "@mui/material";
3433
+ import { jsx as jsx129, jsxs as jsxs123 } from "react/jsx-runtime";
3080
3434
  var EventDetailsHeader = ({ event, onClose }) => {
3081
- return /* @__PURE__ */ jsxs122(
3082
- Box6,
3435
+ return /* @__PURE__ */ jsxs123(
3436
+ Box7,
3083
3437
  {
3084
3438
  sx: {
3085
3439
  alignItems: "center",
@@ -3090,16 +3444,16 @@ var EventDetailsHeader = ({ event, onClose }) => {
3090
3444
  p: 2
3091
3445
  },
3092
3446
  children: [
3093
- /* @__PURE__ */ jsxs122(Box6, { children: [
3094
- /* @__PURE__ */ jsx128(Typography3, { sx: { fontWeight: 600 }, variant: "h6", children: "Event Details" }),
3095
- /* @__PURE__ */ jsxs122(Typography3, { color: "text.secondary", variant: "body2", children: [
3447
+ /* @__PURE__ */ jsxs123(Box7, { children: [
3448
+ /* @__PURE__ */ jsx129(Typography4, { sx: { fontWeight: 600 }, variant: "h6", children: "Event Details" }),
3449
+ /* @__PURE__ */ jsxs123(Typography4, { color: "text.secondary", variant: "body2", children: [
3096
3450
  event.service_name,
3097
3451
  " ",
3098
3452
  "-",
3099
3453
  event.operation_name
3100
3454
  ] })
3101
3455
  ] }),
3102
- onClose && /* @__PURE__ */ jsx128(IconButton, { onClick: onClose, size: "small", children: /* @__PURE__ */ jsx128(Close, {}) })
3456
+ onClose && /* @__PURE__ */ jsx129(IconButton, { onClick: onClose, size: "small", children: /* @__PURE__ */ jsx129(Close, {}) })
3103
3457
  ]
3104
3458
  }
3105
3459
  );
@@ -3107,14 +3461,14 @@ var EventDetailsHeader = ({ event, onClose }) => {
3107
3461
 
3108
3462
  // src/components/event-details/toggle-section.tsx
3109
3463
  import { KeyboardArrowDown, KeyboardArrowRight } from "@mui/icons-material";
3110
- import { Box as Box7, Typography as Typography4 } from "@mui/material";
3111
- import { useState as useState4 } from "react";
3112
- import { jsx as jsx129, jsxs as jsxs123 } from "react/jsx-runtime";
3464
+ import { Box as Box8, Typography as Typography5 } from "@mui/material";
3465
+ import { useState as useState5 } from "react";
3466
+ import { jsx as jsx130, jsxs as jsxs124 } from "react/jsx-runtime";
3113
3467
  var ToggleSection = ({ children, headline, initialOpen = true }) => {
3114
- const [isOpen, setIsOpen] = useState4(initialOpen);
3115
- return /* @__PURE__ */ jsxs123(Box7, { sx: { mt: 4 }, children: [
3116
- /* @__PURE__ */ jsx129(
3117
- Box7,
3468
+ const [isOpen, setIsOpen] = useState5(initialOpen);
3469
+ return /* @__PURE__ */ jsxs124(Box8, { sx: { mt: 4 }, children: [
3470
+ /* @__PURE__ */ jsx130(
3471
+ Box8,
3118
3472
  {
3119
3473
  onClick: () => {
3120
3474
  setIsOpen(!isOpen);
@@ -3123,8 +3477,8 @@ var ToggleSection = ({ children, headline, initialOpen = true }) => {
3123
3477
  cursor: "pointer",
3124
3478
  mb: 1
3125
3479
  },
3126
- children: /* @__PURE__ */ jsxs123(
3127
- Box7,
3480
+ children: /* @__PURE__ */ jsxs124(
3481
+ Box8,
3128
3482
  {
3129
3483
  role: "button",
3130
3484
  sx: {
@@ -3133,73 +3487,73 @@ var ToggleSection = ({ children, headline, initialOpen = true }) => {
3133
3487
  gap: 1
3134
3488
  },
3135
3489
  children: [
3136
- /* @__PURE__ */ jsx129(Typography4, { sx: { fontWeight: 600 }, variant: "subtitle2", children: headline }),
3137
- isOpen ? /* @__PURE__ */ jsx129(KeyboardArrowDown, { sx: { color: "text.secondary", height: 20, width: 20 } }) : /* @__PURE__ */ jsx129(KeyboardArrowRight, { sx: { color: "text.secondary", height: 20, width: 20 } })
3490
+ /* @__PURE__ */ jsx130(Typography5, { sx: { fontWeight: 600 }, variant: "subtitle2", children: headline }),
3491
+ isOpen ? /* @__PURE__ */ jsx130(KeyboardArrowDown, { sx: { color: "text.secondary", height: 20, width: 20 } }) : /* @__PURE__ */ jsx130(KeyboardArrowRight, { sx: { color: "text.secondary", height: 20, width: 20 } })
3138
3492
  ]
3139
3493
  }
3140
3494
  )
3141
3495
  }
3142
3496
  ),
3143
- isOpen && /* @__PURE__ */ jsx129(Box7, { children })
3497
+ isOpen && /* @__PURE__ */ jsx130(Box8, { children })
3144
3498
  ] });
3145
3499
  };
3146
3500
 
3147
3501
  // src/components/event-details/event-details.tsx
3148
- import { Fragment as Fragment2, jsx as jsx130, jsxs as jsxs124 } from "react/jsx-runtime";
3502
+ import { Fragment as Fragment2, jsx as jsx131, jsxs as jsxs125 } from "react/jsx-runtime";
3149
3503
  var EventDetails = ({ selectedEvent }) => {
3150
3504
  if (!selectedEvent) {
3151
- return /* @__PURE__ */ jsx130(Box8, { sx: { p: 3, textAlign: "center" }, children: /* @__PURE__ */ jsx130(Typography5, { color: "text.secondary", variant: "body2", children: "Select an event to view details" }) });
3505
+ return /* @__PURE__ */ jsx131(Box9, { sx: { p: 3, textAlign: "center" }, children: /* @__PURE__ */ jsx131(Typography6, { color: "text.secondary", variant: "body2", children: "Select an event to view details" }) });
3152
3506
  }
3153
- return /* @__PURE__ */ jsxs124(Box8, { "data-testid": "event-details", sx: { display: "flex", flexDirection: "column", height: "100%" }, children: [
3154
- /* @__PURE__ */ jsx130(EventDetailsHeader, { event: selectedEvent }),
3155
- /* @__PURE__ */ jsx130(Box8, { sx: { flexGrow: 1, overflow: "auto", p: 2 }, children: /* @__PURE__ */ jsxs124(Stack, { spacing: 2, children: [
3156
- /* @__PURE__ */ jsx130(ToggleSection, { headline: "Basic Information", children: /* @__PURE__ */ jsxs124(Stack, { spacing: 1, children: [
3157
- /* @__PURE__ */ jsxs124(Box8, { children: [
3158
- /* @__PURE__ */ jsx130(Typography5, { color: "text.secondary", variant: "caption", children: "Span ID" }),
3159
- /* @__PURE__ */ jsx130(Typography5, { variant: "body2", children: selectedEvent.span_id })
3507
+ return /* @__PURE__ */ jsxs125(Box9, { "data-testid": "event-details", sx: { display: "flex", flexDirection: "column", height: "100%" }, children: [
3508
+ /* @__PURE__ */ jsx131(EventDetailsHeader, { event: selectedEvent }),
3509
+ /* @__PURE__ */ jsx131(Box9, { sx: { flexGrow: 1, overflow: "auto", p: 2 }, children: /* @__PURE__ */ jsxs125(Stack, { spacing: 2, children: [
3510
+ /* @__PURE__ */ jsx131(ToggleSection, { headline: "Basic Information", children: /* @__PURE__ */ jsxs125(Stack, { spacing: 1, children: [
3511
+ /* @__PURE__ */ jsxs125(Box9, { children: [
3512
+ /* @__PURE__ */ jsx131(Typography6, { color: "text.secondary", variant: "caption", children: "Span ID" }),
3513
+ /* @__PURE__ */ jsx131(Typography6, { variant: "body2", children: selectedEvent.span_id })
3160
3514
  ] }),
3161
- /* @__PURE__ */ jsxs124(Box8, { children: [
3162
- /* @__PURE__ */ jsx130(Typography5, { color: "text.secondary", variant: "caption", children: "Trace ID" }),
3163
- /* @__PURE__ */ jsx130(Typography5, { sx: { fontFamily: "monospace", fontSize: "0.85rem" }, variant: "body2", children: selectedEvent.trace_id })
3515
+ /* @__PURE__ */ jsxs125(Box9, { children: [
3516
+ /* @__PURE__ */ jsx131(Typography6, { color: "text.secondary", variant: "caption", children: "Trace ID" }),
3517
+ /* @__PURE__ */ jsx131(Typography6, { sx: { fontFamily: "monospace", fontSize: "0.85rem" }, variant: "body2", children: selectedEvent.trace_id })
3164
3518
  ] }),
3165
- /* @__PURE__ */ jsxs124(Box8, { children: [
3166
- /* @__PURE__ */ jsx130(Typography5, { color: "text.secondary", variant: "caption", children: "Operation" }),
3167
- /* @__PURE__ */ jsx130(Typography5, { variant: "body2", children: selectedEvent.operation_name })
3519
+ /* @__PURE__ */ jsxs125(Box9, { children: [
3520
+ /* @__PURE__ */ jsx131(Typography6, { color: "text.secondary", variant: "caption", children: "Operation" }),
3521
+ /* @__PURE__ */ jsx131(Typography6, { variant: "body2", children: selectedEvent.operation_name })
3168
3522
  ] })
3169
3523
  ] }) }),
3170
- /* @__PURE__ */ jsx130(Divider, {}),
3171
- /* @__PURE__ */ jsx130(ToggleSection, { headline: "Service Information", children: /* @__PURE__ */ jsxs124(Stack, { spacing: 1, children: [
3172
- /* @__PURE__ */ jsxs124(Box8, { children: [
3173
- /* @__PURE__ */ jsx130(Typography5, { color: "text.secondary", variant: "caption", children: "Service" }),
3174
- /* @__PURE__ */ jsx130(Typography5, { variant: "body2", children: selectedEvent.service_name })
3524
+ /* @__PURE__ */ jsx131(Divider, {}),
3525
+ /* @__PURE__ */ jsx131(ToggleSection, { headline: "Service Information", children: /* @__PURE__ */ jsxs125(Stack, { spacing: 1, children: [
3526
+ /* @__PURE__ */ jsxs125(Box9, { children: [
3527
+ /* @__PURE__ */ jsx131(Typography6, { color: "text.secondary", variant: "caption", children: "Service" }),
3528
+ /* @__PURE__ */ jsx131(Typography6, { variant: "body2", children: selectedEvent.service_name })
3175
3529
  ] }),
3176
- /* @__PURE__ */ jsxs124(Box8, { children: [
3177
- /* @__PURE__ */ jsx130(Typography5, { color: "text.secondary", variant: "caption", children: "Resource" }),
3178
- /* @__PURE__ */ jsx130(Typography5, { variant: "body2", children: selectedEvent.resource_name })
3530
+ /* @__PURE__ */ jsxs125(Box9, { children: [
3531
+ /* @__PURE__ */ jsx131(Typography6, { color: "text.secondary", variant: "caption", children: "Resource" }),
3532
+ /* @__PURE__ */ jsx131(Typography6, { variant: "body2", children: selectedEvent.resource_name })
3179
3533
  ] }),
3180
- selectedEvent.region && /* @__PURE__ */ jsxs124(Box8, { children: [
3181
- /* @__PURE__ */ jsx130(Typography5, { color: "text.secondary", variant: "caption", children: "Region" }),
3182
- /* @__PURE__ */ jsx130(Typography5, { variant: "body2", children: selectedEvent.region })
3534
+ selectedEvent.region && /* @__PURE__ */ jsxs125(Box9, { children: [
3535
+ /* @__PURE__ */ jsx131(Typography6, { color: "text.secondary", variant: "caption", children: "Region" }),
3536
+ /* @__PURE__ */ jsx131(Typography6, { variant: "body2", children: selectedEvent.region })
3183
3537
  ] })
3184
3538
  ] }) }),
3185
- /* @__PURE__ */ jsx130(Divider, {}),
3186
- /* @__PURE__ */ jsx130(ToggleSection, { headline: "Timing", children: /* @__PURE__ */ jsxs124(Stack, { spacing: 1, children: [
3187
- /* @__PURE__ */ jsxs124(Box8, { children: [
3188
- /* @__PURE__ */ jsx130(Typography5, { color: "text.secondary", variant: "caption", children: "Start Time" }),
3189
- /* @__PURE__ */ jsx130(Typography5, { variant: "body2", children: unixNanoToDate(selectedEvent.start_time_unix_nano)?.toISOString() })
3539
+ /* @__PURE__ */ jsx131(Divider, {}),
3540
+ /* @__PURE__ */ jsx131(ToggleSection, { headline: "Timing", children: /* @__PURE__ */ jsxs125(Stack, { spacing: 1, children: [
3541
+ /* @__PURE__ */ jsxs125(Box9, { children: [
3542
+ /* @__PURE__ */ jsx131(Typography6, { color: "text.secondary", variant: "caption", children: "Start Time" }),
3543
+ /* @__PURE__ */ jsx131(Typography6, { variant: "body2", children: unixNanoToDate(selectedEvent.start_time_unix_nano)?.toISOString() })
3190
3544
  ] }),
3191
- selectedEvent.end_time_unix_nano && /* @__PURE__ */ jsxs124(Box8, { children: [
3192
- /* @__PURE__ */ jsx130(Typography5, { color: "text.secondary", variant: "caption", children: "Duration" }),
3193
- /* @__PURE__ */ jsxs124(Typography5, { variant: "body2", children: [
3545
+ selectedEvent.end_time_unix_nano && /* @__PURE__ */ jsxs125(Box9, { children: [
3546
+ /* @__PURE__ */ jsx131(Typography6, { color: "text.secondary", variant: "caption", children: "Duration" }),
3547
+ /* @__PURE__ */ jsxs125(Typography6, { variant: "body2", children: [
3194
3548
  ((BigInt(selectedEvent.end_time_unix_nano) - BigInt(selectedEvent.start_time_unix_nano)) / BigInt("1000000")).toString(),
3195
3549
  " ",
3196
3550
  "ms"
3197
3551
  ] })
3198
3552
  ] })
3199
3553
  ] }) }),
3200
- /* @__PURE__ */ jsx130(Divider, {}),
3201
- /* @__PURE__ */ jsx130(ToggleSection, { headline: "Status", children: /* @__PURE__ */ jsxs124(Stack, { direction: "row", spacing: 1, children: [
3202
- /* @__PURE__ */ jsx130(
3554
+ /* @__PURE__ */ jsx131(Divider, {}),
3555
+ /* @__PURE__ */ jsx131(ToggleSection, { headline: "Status", children: /* @__PURE__ */ jsxs125(Stack, { direction: "row", spacing: 1, children: [
3556
+ /* @__PURE__ */ jsx131(
3203
3557
  Chip,
3204
3558
  {
3205
3559
  color: selectedEvent.status_code === 0 ? "success" : "error",
@@ -3207,11 +3561,11 @@ var EventDetails = ({ selectedEvent }) => {
3207
3561
  size: "small"
3208
3562
  }
3209
3563
  ),
3210
- selectedEvent.status_message && /* @__PURE__ */ jsx130(Typography5, { variant: "body2", children: selectedEvent.status_message })
3564
+ selectedEvent.status_message && /* @__PURE__ */ jsx131(Typography6, { variant: "body2", children: selectedEvent.status_message })
3211
3565
  ] }) }),
3212
- selectedEvent.attributes && Object.keys(selectedEvent.attributes).length > 0 && /* @__PURE__ */ jsxs124(Fragment2, { children: [
3213
- /* @__PURE__ */ jsx130(Divider, {}),
3214
- /* @__PURE__ */ jsx130(ToggleSection, { headline: "Attributes", children: /* @__PURE__ */ jsx130(Box8, { sx: { backgroundColor: "#f5f5f5", borderRadius: 1, p: 1 }, children: /* @__PURE__ */ jsx130("pre", { style: { fontSize: "0.85rem", margin: 0, overflow: "auto" }, children: JSON.stringify(selectedEvent.attributes, void 0, 2) }) }) })
3566
+ selectedEvent.attributes && Object.keys(selectedEvent.attributes).length > 0 && /* @__PURE__ */ jsxs125(Fragment2, { children: [
3567
+ /* @__PURE__ */ jsx131(Divider, {}),
3568
+ /* @__PURE__ */ jsx131(ToggleSection, { headline: "Attributes", children: /* @__PURE__ */ jsx131(Box9, { sx: { backgroundColor: "#f5f5f5", borderRadius: 1, p: 1 }, children: /* @__PURE__ */ jsx131("pre", { style: { fontSize: "0.85rem", margin: 0, overflow: "auto" }, children: JSON.stringify(selectedEvent.attributes, void 0, 2) }) }) })
3215
3569
  ] })
3216
3570
  ] }) })
3217
3571
  ] });
@@ -3219,32 +3573,32 @@ var EventDetails = ({ selectedEvent }) => {
3219
3573
 
3220
3574
  // src/components/trace-graph/trace-graph.tsx
3221
3575
  import "@xyflow/react/dist/base.css";
3222
- import { Alert as Alert2, Button as Button3 } from "@mui/material";
3576
+ import { Alert as Alert3, Button as Button4 } from "@mui/material";
3223
3577
  import { Background, Controls, ReactFlow, useReactFlow, useStoreApi } from "@xyflow/react";
3224
- import { useCallback as useCallback5, useEffect as useEffect3, useState as useState5 } from "react";
3578
+ import { useCallback as useCallback6, useEffect as useEffect4, useState as useState6 } from "react";
3225
3579
 
3226
3580
  // src/components/trace-graph/service-node.tsx
3227
- import { Box as Box10, Stack as Stack2, Typography as Typography6 } from "@mui/material";
3581
+ import { Box as Box11, Stack as Stack2, Typography as Typography7 } from "@mui/material";
3228
3582
  import "@xyflow/react/dist/style.css";
3229
3583
  import { Handle, Position } from "@xyflow/react";
3230
- import { memo, useCallback as useCallback4 } from "react";
3584
+ import { memo, useCallback as useCallback5 } from "react";
3231
3585
 
3232
3586
  // src/components/trace-graph/problem-indicator.tsx
3233
3587
  import { Error as ErrorIcon, Info, Warning } from "@mui/icons-material";
3234
- import { Box as Box9, Tooltip as Tooltip2 } from "@mui/material";
3588
+ import { Box as Box10, Tooltip as Tooltip2 } from "@mui/material";
3235
3589
  import { useMemo as useMemo4 } from "react";
3236
- import { jsx as jsx131 } from "react/jsx-runtime";
3590
+ import { jsx as jsx132 } from "react/jsx-runtime";
3237
3591
  var ProblemIndicator = ({ error }) => {
3238
3592
  const icon = useMemo4(() => {
3239
3593
  switch (error.level) {
3240
3594
  case "error": {
3241
- return /* @__PURE__ */ jsx131(ErrorIcon, { sx: { color: "#d32f2f", fontSize: "14px" } });
3595
+ return /* @__PURE__ */ jsx132(ErrorIcon, { sx: { color: "#d32f2f", fontSize: "14px" } });
3242
3596
  }
3243
3597
  case "warning": {
3244
- return /* @__PURE__ */ jsx131(Warning, { sx: { color: "#ff9800", fontSize: "14px" } });
3598
+ return /* @__PURE__ */ jsx132(Warning, { sx: { color: "#ff9800", fontSize: "14px" } });
3245
3599
  }
3246
3600
  default: {
3247
- return /* @__PURE__ */ jsx131(Info, { sx: { color: "#2196f3", fontSize: "14px" } });
3601
+ return /* @__PURE__ */ jsx132(Info, { sx: { color: "#2196f3", fontSize: "14px" } });
3248
3602
  }
3249
3603
  }
3250
3604
  }, [error.level]);
@@ -3261,8 +3615,8 @@ var ProblemIndicator = ({ error }) => {
3261
3615
  }
3262
3616
  }
3263
3617
  }, [error.level]);
3264
- return /* @__PURE__ */ jsx131(Tooltip2, { arrow: true, title: error.message ?? "Issue detected", children: /* @__PURE__ */ jsx131(
3265
- Box9,
3618
+ return /* @__PURE__ */ jsx132(Tooltip2, { arrow: true, title: error.message ?? "Issue detected", children: /* @__PURE__ */ jsx132(
3619
+ Box10,
3266
3620
  {
3267
3621
  sx: {
3268
3622
  alignItems: "center",
@@ -3281,17 +3635,17 @@ var ProblemIndicator = ({ error }) => {
3281
3635
  };
3282
3636
 
3283
3637
  // src/components/trace-graph/service-node.tsx
3284
- import { jsx as jsx132, jsxs as jsxs125 } from "react/jsx-runtime";
3638
+ import { jsx as jsx133, jsxs as jsxs126 } from "react/jsx-runtime";
3285
3639
  var handleStyle = {
3286
3640
  backgroundColor: "white",
3287
3641
  borderColor: "lightgray",
3288
3642
  opacity: 0
3289
3643
  };
3290
3644
  var ServiceNode = memo(function ServiceNode2({ data, selected }) {
3291
- const handleClick = useCallback4(() => {
3645
+ const handleClick = useCallback5(() => {
3292
3646
  data.onEventSelect(data.event);
3293
3647
  }, [data]);
3294
- const handleKeyPress = useCallback4(
3648
+ const handleKeyPress = useCallback5(
3295
3649
  (event) => {
3296
3650
  if (event.key === "Enter" || event.key === " ") {
3297
3651
  handleClick();
@@ -3300,9 +3654,9 @@ var ServiceNode = memo(function ServiceNode2({ data, selected }) {
3300
3654
  [handleClick]
3301
3655
  );
3302
3656
  const hasErrors = (data.event.errors && data.event.errors.length > 0) ?? false;
3303
- return /* @__PURE__ */ jsxs125(Box10, { sx: { maxWidth: 200 }, children: [
3304
- /* @__PURE__ */ jsxs125(
3305
- Box10,
3657
+ return /* @__PURE__ */ jsxs126(Box11, { sx: { maxWidth: 200 }, children: [
3658
+ /* @__PURE__ */ jsxs126(
3659
+ Box11,
3306
3660
  {
3307
3661
  onClick: handleClick,
3308
3662
  onKeyPress: handleKeyPress,
@@ -3324,9 +3678,9 @@ var ServiceNode = memo(function ServiceNode2({ data, selected }) {
3324
3678
  },
3325
3679
  tabIndex: 0,
3326
3680
  children: [
3327
- /* @__PURE__ */ jsx132(Handle, { position: Position.Left, style: handleStyle, type: "target" }),
3328
- /* @__PURE__ */ jsx132(Handle, { position: Position.Right, style: handleStyle, type: "source" }),
3329
- /* @__PURE__ */ jsx132(
3681
+ /* @__PURE__ */ jsx133(Handle, { position: Position.Left, style: handleStyle, type: "target" }),
3682
+ /* @__PURE__ */ jsx133(Handle, { position: Position.Right, style: handleStyle, type: "source" }),
3683
+ /* @__PURE__ */ jsx133(
3330
3684
  ServiceCell,
3331
3685
  {
3332
3686
  borderColor: selected ? "black" : "lightgray",
@@ -3340,7 +3694,7 @@ var ServiceNode = memo(function ServiceNode2({ data, selected }) {
3340
3694
  ]
3341
3695
  }
3342
3696
  ),
3343
- /* @__PURE__ */ jsxs125(
3697
+ /* @__PURE__ */ jsxs126(
3344
3698
  Stack2,
3345
3699
  {
3346
3700
  alignItems: "center",
@@ -3351,7 +3705,7 @@ var ServiceNode = memo(function ServiceNode2({ data, selected }) {
3351
3705
  mt: 0.5
3352
3706
  },
3353
3707
  children: [
3354
- hasErrors && /* @__PURE__ */ jsx132(
3708
+ hasErrors && /* @__PURE__ */ jsx133(
3355
3709
  Stack2,
3356
3710
  {
3357
3711
  direction: "row",
@@ -3360,11 +3714,11 @@ var ServiceNode = memo(function ServiceNode2({ data, selected }) {
3360
3714
  flexWrap: "wrap",
3361
3715
  gap: "2px"
3362
3716
  },
3363
- children: data.event.errors?.map((error) => /* @__PURE__ */ jsx132(ProblemIndicator, { error }, error.span_id))
3717
+ children: data.event.errors?.map((error) => /* @__PURE__ */ jsx133(ProblemIndicator, { error }, error.span_id))
3364
3718
  }
3365
3719
  ),
3366
- /* @__PURE__ */ jsx132(
3367
- Typography6,
3720
+ /* @__PURE__ */ jsx133(
3721
+ Typography7,
3368
3722
  {
3369
3723
  sx: {
3370
3724
  fontSize: "0.9rem",
@@ -3477,7 +3831,7 @@ var calculateCenterX = (focusNodeX, viewPortPixelWidth, minX, maxX) => {
3477
3831
  };
3478
3832
 
3479
3833
  // src/components/trace-graph/trace-graph.tsx
3480
- import { Fragment as Fragment3, jsx as jsx133, jsxs as jsxs126 } from "react/jsx-runtime";
3834
+ import { Fragment as Fragment3, jsx as jsx134, jsxs as jsxs127 } from "react/jsx-runtime";
3481
3835
  var nodeTypes = {
3482
3836
  service: ServiceNode
3483
3837
  };
@@ -3487,15 +3841,15 @@ var TraceGraph = ({
3487
3841
  traceId,
3488
3842
  viewPortPixelWidth
3489
3843
  }) => {
3490
- const [nodes, setNodes] = useState5([]);
3491
- const [edges, setEdges] = useState5([]);
3492
- const [isLoading, setIsLoading] = useState5(true);
3493
- const [initialViewSet, setInitialViewSet] = useState5(false);
3844
+ const [nodes, setNodes] = useState6([]);
3845
+ const [edges, setEdges] = useState6([]);
3846
+ const [isLoading, setIsLoading] = useState6(true);
3847
+ const [initialViewSet, setInitialViewSet] = useState6(false);
3494
3848
  const { fitView, setCenter } = useReactFlow();
3495
3849
  const store = useStoreApi();
3496
3850
  const api = useAppInspectorApi();
3497
- const [fetchError, setFetchError] = useState5();
3498
- const updateSelectedNode = useCallback5(
3851
+ const [fetchError, setFetchError] = useState6();
3852
+ const updateSelectedNode = useCallback6(
3499
3853
  (nodeId) => {
3500
3854
  const { addSelectedNodes } = store.getState();
3501
3855
  if (nodeId) {
@@ -3507,7 +3861,7 @@ var TraceGraph = ({
3507
3861
  },
3508
3862
  [nodes, store]
3509
3863
  );
3510
- const fetchTrace = useCallback5(async () => {
3864
+ const fetchTrace = useCallback6(async () => {
3511
3865
  setIsLoading(true);
3512
3866
  try {
3513
3867
  const response = await api.getSpans({ trace_id: traceId });
@@ -3550,13 +3904,13 @@ var TraceGraph = ({
3550
3904
  setIsLoading(false);
3551
3905
  }
3552
3906
  }, [api, traceId, onEventSelect]);
3553
- const fetchTraceSync = useCallback5(() => {
3907
+ const fetchTraceSync = useCallback6(() => {
3554
3908
  void fetchTrace();
3555
3909
  }, [fetchTrace]);
3556
- useEffect3(() => {
3910
+ useEffect4(() => {
3557
3911
  fetchTraceSync();
3558
3912
  }, [fetchTraceSync]);
3559
- useEffect3(() => {
3913
+ useEffect4(() => {
3560
3914
  const shouldSetInitialView = !isLoading && nodes.length > 0 && !initialViewSet;
3561
3915
  if (shouldSetInitialView) {
3562
3916
  if (initialFocusEventId) {
@@ -3576,20 +3930,20 @@ var TraceGraph = ({
3576
3930
  setInitialViewSet(true);
3577
3931
  }
3578
3932
  }, [isLoading, nodes, initialFocusEventId, viewPortPixelWidth, setCenter, fitView, onEventSelect, initialViewSet]);
3579
- useEffect3(() => {
3933
+ useEffect4(() => {
3580
3934
  if (initialFocusEventId) {
3581
3935
  updateSelectedNode(initialFocusEventId);
3582
3936
  }
3583
3937
  }, [initialFocusEventId, updateSelectedNode]);
3584
- const onNodeClick = useCallback5((_event, node) => {
3938
+ const onNodeClick = useCallback6((_event, node) => {
3585
3939
  onEventSelect(node.data.event);
3586
3940
  updateSelectedNode(node.id);
3587
3941
  }, [onEventSelect, updateSelectedNode]);
3588
- return /* @__PURE__ */ jsxs126(Fragment3, { children: [
3589
- fetchError && /* @__PURE__ */ jsxs126(
3590
- Alert2,
3942
+ return /* @__PURE__ */ jsxs127(Fragment3, { children: [
3943
+ fetchError && /* @__PURE__ */ jsxs127(
3944
+ Alert3,
3591
3945
  {
3592
- action: /* @__PURE__ */ jsx133(Button3, { onClick: fetchTraceSync, children: "Retry" }),
3946
+ action: /* @__PURE__ */ jsx134(Button4, { onClick: fetchTraceSync, children: "Retry" }),
3593
3947
  severity: "error",
3594
3948
  children: [
3595
3949
  "Unexpected error:",
@@ -3598,7 +3952,7 @@ var TraceGraph = ({
3598
3952
  ]
3599
3953
  }
3600
3954
  ),
3601
- /* @__PURE__ */ jsxs126(
3955
+ /* @__PURE__ */ jsxs127(
3602
3956
  ReactFlow,
3603
3957
  {
3604
3958
  "data-testid": "trace-graph",
@@ -3612,8 +3966,8 @@ var TraceGraph = ({
3612
3966
  onNodeClick,
3613
3967
  selectNodesOnDrag: false,
3614
3968
  children: [
3615
- /* @__PURE__ */ jsx133(Controls, { showInteractive: false }),
3616
- /* @__PURE__ */ jsx133(Background, {})
3969
+ /* @__PURE__ */ jsx134(Controls, { showInteractive: false }),
3970
+ /* @__PURE__ */ jsx134(Background, {})
3617
3971
  ]
3618
3972
  }
3619
3973
  )
@@ -3621,7 +3975,7 @@ var TraceGraph = ({
3621
3975
  };
3622
3976
 
3623
3977
  // src/pages/trace-graph.tsx
3624
- import { jsx as jsx134, jsxs as jsxs127 } from "react/jsx-runtime";
3978
+ import { Fragment as Fragment4, jsx as jsx135, jsxs as jsxs128 } from "react/jsx-runtime";
3625
3979
  var HEADER_HEIGHT = 56;
3626
3980
  var DRAWER_WIDTH = "35%";
3627
3981
  var Main = styled("main", { shouldForwardProp: (property) => property !== "open" })(({ open, theme }) => ({
@@ -3657,10 +4011,11 @@ var TraceGraphPage = () => {
3657
4011
  const { traceId } = useParams();
3658
4012
  const [searchParameters] = useSearchParams();
3659
4013
  const spanId = searchParameters.get("spanId");
3660
- const [open, setOpen] = useState6(true);
3661
- const [selectedEvent, setSelectedEvent] = useState6();
3662
- const [viewPortPixelWidth, setViewPortPixelWidth] = useState6(0);
3663
- const calculateDrawerWidth = useCallback6(() => {
4014
+ const [open, setOpen] = useState7(true);
4015
+ const [selectedEvent, setSelectedEvent] = useState7();
4016
+ const [viewPortPixelWidth, setViewPortPixelWidth] = useState7(0);
4017
+ const { checkStatus, error: statusError, status } = useStatus();
4018
+ const calculateDrawerWidth = useCallback7(() => {
3664
4019
  const percentageMatch = /(\d+)%/.exec(DRAWER_WIDTH);
3665
4020
  if (percentageMatch && open) {
3666
4021
  const percentage = Number.parseInt(percentageMatch[1], 10);
@@ -3668,7 +4023,7 @@ var TraceGraphPage = () => {
3668
4023
  }
3669
4024
  return 0;
3670
4025
  }, [open]);
3671
- useEffect4(() => {
4026
+ useEffect5(() => {
3672
4027
  const updateViewportWidth = () => {
3673
4028
  const totalWidth = window.innerWidth;
3674
4029
  const drawerPixelWidth = open ? calculateDrawerWidth() : 0;
@@ -3682,12 +4037,16 @@ var TraceGraphPage = () => {
3682
4037
  clearTimeout(timeoutId);
3683
4038
  };
3684
4039
  }, [open, calculateDrawerWidth]);
3685
- const handleEventSelect = useCallback6((event) => {
4040
+ const handleEventSelect = useCallback7((event) => {
3686
4041
  setSelectedEvent(event);
3687
4042
  setOpen(true);
3688
4043
  }, []);
3689
- return /* @__PURE__ */ jsx134(
3690
- Box11,
4044
+ const handleRetry = useCallback7(() => {
4045
+ void checkStatus();
4046
+ }, [checkStatus]);
4047
+ const shouldShowStatusMessage = Boolean(statusError) || status?.status === "DISABLED";
4048
+ return /* @__PURE__ */ jsx135(
4049
+ Box12,
3691
4050
  {
3692
4051
  "data-testid": "trace-graph-page",
3693
4052
  sx: {
@@ -3697,7 +4056,7 @@ var TraceGraphPage = () => {
3697
4056
  height: "100vh",
3698
4057
  overflow: "hidden"
3699
4058
  },
3700
- children: /* @__PURE__ */ jsxs127(
4059
+ children: /* @__PURE__ */ jsx135(
3701
4060
  Paper2,
3702
4061
  {
3703
4062
  sx: {
@@ -3707,15 +4066,22 @@ var TraceGraphPage = () => {
3707
4066
  position: "relative",
3708
4067
  width: "100%"
3709
4068
  },
3710
- children: [
3711
- /* @__PURE__ */ jsx134(Main, { open, children: /* @__PURE__ */ jsx134(
3712
- Box11,
4069
+ children: shouldShowStatusMessage ? /* @__PURE__ */ jsx135(
4070
+ StatusMessage,
4071
+ {
4072
+ error: statusError,
4073
+ onRetry: handleRetry,
4074
+ status
4075
+ }
4076
+ ) : /* @__PURE__ */ jsxs128(Fragment4, { children: [
4077
+ /* @__PURE__ */ jsx135(Main, { open, children: /* @__PURE__ */ jsx135(
4078
+ Box12,
3713
4079
  {
3714
4080
  sx: {
3715
4081
  height: "100%",
3716
4082
  overflow: "auto"
3717
4083
  },
3718
- children: traceId !== void 0 && /* @__PURE__ */ jsx134(ReactFlowProvider, { children: /* @__PURE__ */ jsx134(
4084
+ children: traceId !== void 0 && /* @__PURE__ */ jsx135(ReactFlowProvider, { children: /* @__PURE__ */ jsx135(
3719
4085
  TraceGraph,
3720
4086
  {
3721
4087
  initialFocusEventId: spanId,
@@ -3726,8 +4092,8 @@ var TraceGraphPage = () => {
3726
4092
  ) })
3727
4093
  }
3728
4094
  ) }),
3729
- /* @__PURE__ */ jsx134(StyledDrawer, { anchor: "right", open, variant: "persistent", children: /* @__PURE__ */ jsx134(EventDetails, { selectedEvent }) })
3730
- ]
4095
+ /* @__PURE__ */ jsx135(StyledDrawer, { anchor: "right", open, variant: "persistent", children: /* @__PURE__ */ jsx135(EventDetails, { selectedEvent }) })
4096
+ ] })
3731
4097
  }
3732
4098
  )
3733
4099
  }