[Synthetics] Fix date format for Waterfall and TLS Certificates (#162099)

Fixes #161499 

## Summary
The PR adjusts date format in waterfall flyout and TLS Certificates page
to the common date format used in Synthetics (via `useDateFormat` hook).

|Before|After|
|:---:|:---:|
|<img width="438" alt="Screenshot 2023-07-18 at 00 25 48"
src="f671c5f0-042d-4fa1-910e-bc9deb85d1dd">|<img
width="438" alt="Screenshot 2023-07-17 at 23 40 59"
src="bf19344f-e82e-4188-97a2-65d045544245">|

|Before|After|
|:---:|:---:|
|<img width="1545" alt="Screenshot 2023-07-18 at 00 25 05"
src="ddeb4186-c1e1-4eff-b8ed-4ea6755b3e09">|<img
width="1544" alt="Screenshot 2023-07-17 at 23 53 55"
src="b35a34ea-3d16-4479-82db-0a2f808d0a6c">|
This commit is contained in:
Abdul Wahab Zahid 2023-07-18 12:19:47 +02:00 committed by GitHub
parent 82eaddd86c
commit 37521304af
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 48 additions and 22 deletions

View file

@ -9,6 +9,7 @@ import React from 'react';
import moment from 'moment';
import { Direction, EuiBasicTable } from '@elastic/eui';
import { Cert, CertMonitor, CertResult } from '../../../../../common/runtime_types';
import { useDateFormat } from '../../../../hooks/use_date_format';
import { CertStatus } from './cert_status';
import { CertMonitors } from './cert_monitors';
import * as labels from './translations';
@ -46,6 +47,7 @@ interface Props {
}
export const CertificateList: React.FC<Props> = ({ page, certificates, sort, onChange }) => {
const dateFormatter = useDateFormat();
const pagination = {
pageIndex: page.index,
pageSize: page.size,
@ -80,7 +82,7 @@ export const CertificateList: React.FC<Props> = ({ page, certificates, sort, onC
name: labels.VALID_UNTIL_COL,
field: 'not_after',
sortable: true,
render: (value: string) => moment(value).format('L LT'),
render: dateFormatter,
},
{
name: labels.AGE_COL,

View file

@ -14,6 +14,7 @@ import {
} from './data_formatting';
import { MimeType, FriendlyFlyoutLabels, FriendlyTimingLabels, Timings, Metadata } from './types';
import { WaterfallDataEntry } from './types';
import type { DateFormatter } from '../../../../../../hooks/use_date_format';
import { mockMoment } from '../../../../utils/formatting/test_helpers';
import { NetworkEvent } from '../../../../../../../common/runtime_types';
@ -231,12 +232,14 @@ describe('Palettes', () => {
});
describe('getSeriesAndDomain', () => {
let mockDateFormatter: DateFormatter;
beforeEach(() => {
mockMoment();
mockDateFormatter = (dateStr?: string) => (dateStr ? moment(dateStr).format() : '');
});
it('formats series timings', () => {
const actual = getSeriesAndDomain(networkItems);
const actual = getSeriesAndDomain(networkItems, false, mockDateFormatter);
expect(actual.series).toMatchInlineSnapshot(`
Array [
Object {
@ -409,7 +412,7 @@ describe('getSeriesAndDomain', () => {
});
it('handles series formatting when only total timing values are available', () => {
const { series } = getSeriesAndDomain(networkItemsWithoutFullTimings);
const { series } = getSeriesAndDomain(networkItemsWithoutFullTimings, false, mockDateFormatter);
expect(series).toMatchInlineSnapshot(`
Array [
Object {
@ -536,7 +539,7 @@ describe('getSeriesAndDomain', () => {
});
it('handles series formatting when there is no timing information available', () => {
const { series } = getSeriesAndDomain(networkItemsWithoutAnyTimings);
const { series } = getSeriesAndDomain(networkItemsWithoutAnyTimings, false, mockDateFormatter);
expect(series).toMatchInlineSnapshot(`
Array [
Object {
@ -555,7 +558,7 @@ describe('getSeriesAndDomain', () => {
});
it('handles formatting when there is no timing information available', () => {
const actual = getSeriesAndDomain(networkItemsWithoutAnyTimings);
const actual = getSeriesAndDomain(networkItemsWithoutAnyTimings, false, mockDateFormatter);
expect(actual).toMatchInlineSnapshot(`
Object {
"domain": Object {
@ -636,7 +639,11 @@ describe('getSeriesAndDomain', () => {
});
it('handles formatting when the timings object is undefined', () => {
const { series } = getSeriesAndDomain(networkItemsWithoutTimingsObject);
const { series } = getSeriesAndDomain(
networkItemsWithoutTimingsObject,
false,
mockDateFormatter
);
expect(series).toMatchInlineSnapshot(`
Array [
Object {
@ -653,7 +660,11 @@ describe('getSeriesAndDomain', () => {
});
it('handles formatting when mime type is not mapped to a specific mime type bucket', () => {
const { series } = getSeriesAndDomain(networkItemsWithUnknownMimeType);
const { series } = getSeriesAndDomain(
networkItemsWithUnknownMimeType,
false,
mockDateFormatter
);
/* verify that raw mime type appears in the tooltip config and that
* the colour is mapped to mime type other */
const contentDownloadingConfigItem = series.find((item: WaterfallDataEntry) => {
@ -682,7 +693,7 @@ describe('getSeriesAndDomain', () => {
[FriendlyFlyoutLabels[Metadata.ResourceSize], '1.000 KB'],
[FriendlyFlyoutLabels[Metadata.IP], '104.18.8.22'],
])('handles metadata details formatting', (name, value) => {
const { metadata } = getSeriesAndDomain(networkItems);
const { metadata } = getSeriesAndDomain(networkItems, false, mockDateFormatter);
const metadataEntry = metadata[0];
expect(
metadataEntry.details.find((item) => item.value === value && item.name === name)
@ -690,7 +701,7 @@ describe('getSeriesAndDomain', () => {
});
it('handles metadata headers formatting', () => {
const { metadata } = getSeriesAndDomain(networkItems);
const { metadata } = getSeriesAndDomain(networkItems, false, mockDateFormatter);
const metadataEntry = metadata[0];
metadataEntry.requestHeaders?.forEach((header) => {
expect(header).toEqual({ name: header.name, value: header.value });
@ -701,7 +712,7 @@ describe('getSeriesAndDomain', () => {
});
it('handles certificate formatting', () => {
const { metadata } = getSeriesAndDomain([networkItems[0]]);
const { metadata } = getSeriesAndDomain([networkItems[0]], false, mockDateFormatter);
const metadataEntry = metadata[0];
expect(metadataEntry.certificates).toEqual([
{ name: 'Issuer', value: networkItems[0].certificates?.issuer },
@ -715,13 +726,15 @@ describe('getSeriesAndDomain', () => {
});
it('counts the total number of highlighted items', () => {
// only one CSS file in this array of network Items
const actual = getSeriesAndDomain(networkItems, false, '', ['stylesheet']);
const actual = getSeriesAndDomain(networkItems, false, mockDateFormatter, '', ['stylesheet']);
expect(actual.totalHighlightedRequests).toBe(1);
});
it('adds isHighlighted to waterfall entry when filter matches', () => {
// only one CSS file in this array of network Items
const { series } = getSeriesAndDomain(networkItems, false, '', ['stylesheet']);
const { series } = getSeriesAndDomain(networkItems, false, mockDateFormatter, '', [
'stylesheet',
]);
series.forEach((item) => {
if (item.x === 0) {
expect(item.config.isHighlighted).toBe(true);
@ -733,7 +746,7 @@ describe('getSeriesAndDomain', () => {
it('adds isHighlighted to waterfall entry when query matches', () => {
// only the second item matches this query
const { series } = getSeriesAndDomain(networkItems, false, 'director', []);
const { series } = getSeriesAndDomain(networkItems, false, mockDateFormatter, 'director', []);
series.forEach((item) => {
if (item.x === 1) {
expect(item.config.isHighlighted).toBe(true);

View file

@ -6,9 +6,9 @@
*/
import { euiPaletteColorBlind } from '@elastic/eui';
import moment from 'moment';
import { MarkerItems } from '../../step_waterfall_chart/waterfall/context/waterfall_context';
import type { DateFormatter } from '../../../../../../hooks/use_date_format';
import { NetworkEvent } from '../../../../../../../common/runtime_types';
import { WaterfallData, WaterfallMetadata } from './types';
import {
@ -128,6 +128,7 @@ export const getFilterMatcher = (filters: string[] | undefined): ItemMatcher =>
export const getSeriesAndDomain = (
items: NetworkEvent[],
onlyHighlighted = false,
dateFormatter: DateFormatter,
query?: string,
activeFilters?: string[],
markerItems?: MarkerItems
@ -159,7 +160,7 @@ export const getSeriesAndDomain = (
const mimeTypeColour = getColourForMimeType(item.mimeType);
const offsetValue = getValueForOffset(item);
let currentOffset = offsetValue - zeroOffset;
metadata.push(formatMetadata({ item, index, requestStart: currentOffset }));
metadata.push(formatMetadata({ item, index, requestStart: currentOffset, dateFormatter }));
const isHighlighted = isHighlightedItem(item, queryMatcher, filterMatcher);
if (isHighlighted) {
totalHighlightedRequests++;
@ -270,10 +271,12 @@ const formatMetadata = ({
item,
index,
requestStart,
dateFormatter,
}: {
item: NetworkEvent;
index: number;
requestStart: number;
dateFormatter: DateFormatter;
}) => {
const {
certificates,
@ -301,13 +304,11 @@ const formatMetadata = ({
},
{
name: FriendlyFlyoutLabels[Metadata.CertificateIssueDate],
value: certificates.validFrom
? moment(certificates.validFrom).format('L LT')
: undefined,
value: certificates.validFrom ? dateFormatter(certificates.validFrom) : undefined,
},
{
name: FriendlyFlyoutLabels[Metadata.CertificateExpiryDate],
value: certificates.validTo ? moment(certificates.validTo).format('L LT') : undefined,
value: certificates.validTo ? dateFormatter(certificates.validTo) : undefined,
},
{
name: FriendlyFlyoutLabels[Metadata.CertificateSubject],

View file

@ -9,6 +9,7 @@ import React, { useCallback, useMemo, useState } from 'react';
import useLocalStorage from 'react-use/lib/useLocalStorage';
import { EuiHealth } from '@elastic/eui';
import { JourneyStep, NetworkEvent } from '../../../../../../../common/runtime_types';
import { useDateFormat } from '../../../../../../hooks/use_date_format';
import { getSeriesAndDomain, getSidebarItems } from '../../common/network_data/data_formatting';
import { SidebarItem, LegendItem } from '../../common/network_data/types';
import { RenderItem, WaterfallDataEntry } from '../../common/network_data/types';
@ -54,9 +55,17 @@ export const WaterfallChartWrapper: React.FC<Props> = ({
const hasFilters = activeFilters.length > 0;
const dateFormatter = useDateFormat();
const { series, domain, metadata, totalHighlightedRequests } = useMemo(() => {
return getSeriesAndDomain(networkData, onlyHighlighted, query, activeFilters, markerItems);
}, [networkData, query, activeFilters, onlyHighlighted, markerItems]);
return getSeriesAndDomain(
networkData,
onlyHighlighted,
dateFormatter,
query,
activeFilters,
markerItems
);
}, [networkData, dateFormatter, query, activeFilters, onlyHighlighted, markerItems]);
const sidebarItems = useMemo(() => {
return getSidebarItems(networkData, onlyHighlighted ?? false, query, activeFilters);

View file

@ -9,7 +9,8 @@ import moment from 'moment';
import { useEffect } from 'react';
import { i18n } from '@kbn/i18n';
export function useDateFormat(): (timestamp?: string) => string {
export type DateFormatter = (timestamp?: string) => string;
export function useDateFormat(): DateFormatter {
const kibanaLocale = i18n.getLocale();
const clientLocale = navigator.language;