New: Improve history details for release grabs

pull/2182/head
Bogdan 5 months ago
parent c7dfde0ce9
commit 96f49da79e

@ -3,6 +3,7 @@ import React from 'react';
import DescriptionList from 'Components/DescriptionList/DescriptionList';
import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem';
import Link from 'Components/Link/Link';
import formatDateTime from 'Utilities/Date/formatDateTime';
import translate from 'Utilities/String/translate';
import styles from './HistoryDetails.css';
@ -10,7 +11,10 @@ function HistoryDetails(props) {
const {
indexer,
eventType,
data
date,
data,
shortDateFormat,
timeFormat
} = props;
if (eventType === 'indexerQuery' || eventType === 'indexerRss') {
@ -22,7 +26,9 @@ function HistoryDetails(props) {
offset,
source,
host,
url
url,
elapsedTime,
cached
} = data;
return (
@ -104,6 +110,24 @@ function HistoryDetails(props) {
/> :
null
}
{
elapsedTime ?
<DescriptionListItem
title={translate('ElapsedTime')}
data={`${elapsedTime}ms${cached === '1' ? ' (cached)' : null}`}
/> :
null
}
{
date ?
<DescriptionListItem
title={translate('Date')}
data={formatDateTime(date, shortDateFormat, timeFormat, { includeSeconds: true })}
/> :
null
}
</DescriptionList>
);
}
@ -111,10 +135,19 @@ function HistoryDetails(props) {
if (eventType === 'releaseGrabbed') {
const {
source,
host,
grabTitle,
url
url,
publishedDate,
infoUrl,
downloadClient,
downloadClientName,
elapsedTime,
grabMethod
} = data;
const downloadClientNameInfo = downloadClientName ?? downloadClient;
return (
<DescriptionList>
{
@ -135,6 +168,15 @@ function HistoryDetails(props) {
null
}
{
data ?
<DescriptionListItem
title={translate('Host')}
data={host}
/> :
null
}
{
data ?
<DescriptionListItem
@ -144,6 +186,33 @@ function HistoryDetails(props) {
null
}
{
infoUrl ?
<DescriptionListItem
title={translate('InfoUrl')}
data={<Link to={infoUrl}>{infoUrl}</Link>}
/> :
null
}
{
publishedDate ?
<DescriptionListItem
title={translate('PublishedDate')}
data={formatDateTime(publishedDate, shortDateFormat, timeFormat, { includeSeconds: true })}
/> :
null
}
{
downloadClientNameInfo ?
<DescriptionListItem
title={translate('DownloadClient')}
data={downloadClientNameInfo}
/> :
null
}
{
data ?
<DescriptionListItem
@ -152,11 +221,40 @@ function HistoryDetails(props) {
/> :
null
}
{
elapsedTime ?
<DescriptionListItem
title={translate('ElapsedTime')}
data={`${elapsedTime}ms`}
/> :
null
}
{
grabMethod ?
<DescriptionListItem
title={translate('Redirected')}
data={grabMethod.toLowerCase() === 'redirect' ? translate('Yes') : translate('No')}
/> :
null
}
{
date ?
<DescriptionListItem
title={translate('Date')}
data={formatDateTime(date, shortDateFormat, timeFormat, { includeSeconds: true })}
/> :
null
}
</DescriptionList>
);
}
if (eventType === 'indexerAuth') {
const { elapsedTime } = data;
return (
<DescriptionList
descriptionClassName={styles.description}
@ -170,6 +268,24 @@ function HistoryDetails(props) {
/> :
null
}
{
elapsedTime ?
<DescriptionListItem
title={translate('ElapsedTime')}
data={`${elapsedTime}ms`}
/> :
null
}
{
date ?
<DescriptionListItem
title={translate('Date')}
data={formatDateTime(date, shortDateFormat, timeFormat, { includeSeconds: true })}
/> :
null
}
</DescriptionList>
);
}
@ -181,6 +297,15 @@ function HistoryDetails(props) {
title={translate('Name')}
data={data.query}
/>
{
date ?
<DescriptionListItem
title={translate('Date')}
data={formatDateTime(date, shortDateFormat, timeFormat, { includeSeconds: true })}
/> :
null
}
</DescriptionList>
);
}
@ -188,6 +313,7 @@ function HistoryDetails(props) {
HistoryDetails.propTypes = {
indexer: PropTypes.object.isRequired,
eventType: PropTypes.string.isRequired,
date: PropTypes.string.isRequired,
data: PropTypes.object.isRequired,
shortDateFormat: PropTypes.string.isRequired,
timeFormat: PropTypes.string.isRequired

@ -29,6 +29,7 @@ function HistoryDetailsModal(props) {
isOpen,
eventType,
indexer,
date,
data,
shortDateFormat,
timeFormat,
@ -49,6 +50,7 @@ function HistoryDetailsModal(props) {
<HistoryDetails
eventType={eventType}
indexer={indexer}
date={date}
data={data}
shortDateFormat={shortDateFormat}
timeFormat={timeFormat}
@ -71,6 +73,7 @@ HistoryDetailsModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
eventType: PropTypes.string.isRequired,
indexer: PropTypes.object.isRequired,
date: PropTypes.string.isRequired,
data: PropTypes.object.isRequired,
shortDateFormat: PropTypes.string.isRequired,
timeFormat: PropTypes.string.isRequired,

@ -20,21 +20,22 @@ function getIconName(eventType) {
}
}
function getIconKind(successful) {
switch (successful) {
case false:
return kinds.DANGER;
default:
return kinds.DEFAULT;
function getIconKind(successful, redirect) {
if (redirect) {
return kinds.INFO;
} else if (!successful) {
return kinds.DANGER;
}
return kinds.DEFAULT;
}
function getTooltip(eventType, data, indexer) {
function getTooltip(eventType, data, indexer, redirect) {
switch (eventType) {
case 'indexerQuery':
return `Query "${data.query}" sent to ${indexer.name}`;
case 'releaseGrabbed':
return `Release grabbed from ${indexer.name}`;
return redirect ? `Release grabbed via redirect from ${indexer.name}` : `Release grabbed from ${indexer.name}`;
case 'indexerAuth':
return `Auth attempted for ${indexer.name}`;
case 'indexerRss':
@ -45,9 +46,12 @@ function getTooltip(eventType, data, indexer) {
}
function HistoryEventTypeCell({ eventType, successful, data, indexer }) {
const { grabMethod } = data;
const redirect = grabMethod && grabMethod.toLowerCase() === 'redirect';
const iconName = getIconName(eventType);
const iconKind = getIconKind(successful);
const tooltip = getTooltip(eventType, data, indexer);
const iconKind = getIconKind(successful, redirect);
const tooltip = getTooltip(eventType, data, indexer, redirect);
return (
<TableRowCell

@ -370,8 +370,9 @@ class HistoryRow extends Component {
return (
<RelativeDateCell
key={name}
date={date}
className={styles.date}
date={date}
includeSeconds={true}
/>
);
}
@ -408,6 +409,7 @@ class HistoryRow extends Component {
<HistoryDetailsModal
isOpen={this.state.isDetailsModalOpen}
eventType={eventType}
date={date}
data={data}
indexer={indexer}
isMarkingAsFailed={isMarkingAsFailed}

@ -74,7 +74,7 @@ function IndexerHistoryRow(props: IndexerHistoryRowProps) {
</div>
</TableRowCell>
<RelativeDateCell date={date} />
<RelativeDateCell date={date} includeSeconds={true} />
<TableRowCell className={styles.source}>
{data.source ? data.source : null}
@ -91,6 +91,7 @@ function IndexerHistoryRow(props: IndexerHistoryRowProps) {
<HistoryDetailsModal
isOpen={isDetailsModalOpen}
eventType={eventType}
date={date}
data={data}
indexer={indexer}
shortDateFormat={shortDateFormat}

@ -1,4 +1,5 @@
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using NLog;
using NzbDrone.Common.Http;
@ -73,6 +74,9 @@ namespace NzbDrone.Core.Download
GrabTrigger = source == "Prowlarr" ? GrabTrigger.Manual : GrabTrigger.Api
};
var sw = new Stopwatch();
sw.Start();
string downloadClientId;
try
{
@ -111,6 +115,11 @@ namespace NzbDrone.Core.Download
throw;
}
finally
{
sw.Stop();
grabEvent.ElapsedTime = sw.ElapsedMilliseconds;
}
_logger.ProgressInfo("Report sent to {0}. {1}", downloadClient.Definition.Name, downloadTitle);
@ -144,6 +153,9 @@ namespace NzbDrone.Core.Download
GrabTrigger = source == "Prowlarr" ? GrabTrigger.Manual : GrabTrigger.Api
};
var sw = new Stopwatch();
sw.Start();
byte[] downloadedBytes;
try
@ -172,6 +184,11 @@ namespace NzbDrone.Core.Download
_eventAggregator.PublishEvent(grabEvent);
throw;
}
finally
{
sw.Stop();
grabEvent.ElapsedTime = sw.ElapsedMilliseconds;
}
_logger.Trace("Downloaded {0} bytes from {1}", downloadedBytes.Length, link);
_eventAggregator.PublishEvent(grabEvent);

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Net;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Indexers;
@ -203,8 +204,24 @@ namespace NzbDrone.Core.History
history.Data.Add("Host", message.Host ?? string.Empty);
history.Data.Add("GrabMethod", message.Redirect ? "Redirect" : "Proxy");
history.Data.Add("GrabTitle", message.Title);
history.Data.Add("Categories", string.Join(",", message.Release.Categories.Select(x => x.Id) ?? Array.Empty<int>()));
history.Data.Add("Url", message.Url ?? string.Empty);
history.Data.Add("ElapsedTime", message.ElapsedTime.ToString());
if (message.Release.InfoUrl.IsNotNullOrWhiteSpace())
{
history.Data.Add("InfoUrl", message.Release.InfoUrl);
}
if (message.DownloadClient.IsNotNullOrWhiteSpace() || message.DownloadClientName.IsNotNullOrWhiteSpace())
{
history.Data.Add("DownloadClient", message.DownloadClient ?? string.Empty);
history.Data.Add("DownloadClientName", message.DownloadClientName ?? string.Empty);
}
if (message.Release.PublishDate != DateTime.MinValue)
{
history.Data.Add("PublishedDate", message.Release.PublishDate.ToString("s") + "Z");
}
_historyRepository.Insert(history);
}
@ -219,7 +236,7 @@ namespace NzbDrone.Core.History
Successful = message.Successful
};
history.Data.Add("ElapsedTime", message.Time.ToString());
history.Data.Add("ElapsedTime", message.ElapsedTime.ToString());
_historyRepository.Insert(history);
}

@ -6,13 +6,13 @@ namespace NzbDrone.Core.Indexers.Events
{
public int IndexerId { get; set; }
public bool Successful { get; set; }
public long Time { get; set; }
public long ElapsedTime { get; set; }
public IndexerAuthEvent(int indexerId, bool successful, long time)
public IndexerAuthEvent(int indexerId, bool successful, long elapsedTime)
{
IndexerId = indexerId;
Successful = successful;
Time = time;
ElapsedTime = elapsedTime;
}
}
}

@ -18,6 +18,7 @@ namespace NzbDrone.Core.Indexers.Events
public string DownloadId { get; set; }
public IIndexer Indexer { get; set; }
public GrabTrigger GrabTrigger { get; set; }
public long ElapsedTime { get; set; }
public IndexerDownloadEvent(ReleaseInfo release, bool successful, string source, string host, string title, string url)
{

@ -424,6 +424,7 @@
"IndexerVipExpiringHealthCheckMessage": "Indexer VIP benefits expiring soon: {indexerNames}",
"Indexers": "Indexers",
"Info": "Info",
"InfoUrl": "Info URL",
"InitialFailure": "Initial Failure",
"InstanceName": "Instance Name",
"InstanceNameHelpText": "Instance name in tab and for Syslog app name",
@ -555,6 +556,7 @@
"ProxyValidationBadRequest": "Failed to test proxy. Status code: {statusCode}",
"ProxyValidationUnableToConnect": "Unable to connect to proxy: {exceptionMessage}. Check the log surrounding this error for details",
"Public": "Public",
"PublishedDate": "Published Date",
"Publisher": "Publisher",
"Query": "Query",
"QueryOptions": "Query Options",
@ -568,6 +570,7 @@
"Reddit": "Reddit",
"Redirect": "Redirect",
"RedirectHelpText": "Redirect incoming download request for indexer and pass the grab directly instead of proxying the request via {appName}",
"Redirected": "Redirected",
"Refresh": "Refresh",
"RefreshMovie": "Refresh movie",
"ReleaseBranchCheckOfficialBranchMessage": "Branch {0} is not a valid {appName} release branch, you will not receive updates",

Loading…
Cancel
Save