Skip to content

Commit

Permalink
[Synthetics] Fix date format for Waterfall and TLS Certificates (#162099
Browse files Browse the repository at this point in the history
)

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="https://github.com/elastic/kibana/assets/2748376/f671c5f0-042d-4fa1-910e-bc9deb85d1dd">|<img
width="438" alt="Screenshot 2023-07-17 at 23 40 59"
src="https://github.com/elastic/kibana/assets/2748376/bf19344f-e82e-4188-97a2-65d045544245">|

|Before|After|
|:---:|:---:|
|<img width="1545" alt="Screenshot 2023-07-18 at 00 25 05"
src="https://github.com/elastic/kibana/assets/2748376/ddeb4186-c1e1-4eff-b8ed-4ea6755b3e09">|<img
width="1544" alt="Screenshot 2023-07-17 at 23 53 55"
src="https://github.com/elastic/kibana/assets/2748376/b35a34ea-3d16-4479-82db-0a2f808d0a6c">|
  • Loading branch information
awahab07 authored Jul 18, 2023
1 parent 82eaddd commit 3752130
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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 {
Expand All @@ -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) => {
Expand Down Expand Up @@ -682,15 +693,15 @@ 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)
).toBeDefined();
});

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 });
Expand All @@ -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 },
Expand All @@ -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);
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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++;
Expand Down Expand Up @@ -270,10 +271,12 @@ const formatMetadata = ({
item,
index,
requestStart,
dateFormatter,
}: {
item: NetworkEvent;
index: number;
requestStart: number;
dateFormatter: DateFormatter;
}) => {
const {
certificates,
Expand Down Expand Up @@ -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],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion x-pack/plugins/synthetics/public/hooks/use_date_format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down

0 comments on commit 3752130

Please sign in to comment.