Commit c4f4f5f4 authored by Savorboard's avatar Savorboard

upgrade dashoboard module

parent 200d14a8
......@@ -75,5 +75,12 @@ namespace Sample.RabbitMQ.MySql.Controllers
{
Console.WriteLine($@"{DateTime.Now} Subscriber invoked, Info: {p}");
}
[NonAction]
[CapSubscribe("sample.rabbitmq.mysql", Group = "group.test2")]
public void Subscriber2(DateTime p, [FromCap]CapHeader header)
{
Console.WriteLine($@"{DateTime.Now} Subscriber invoked, Info: {p}");
}
}
}
......@@ -8,6 +8,7 @@
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.0.0-rc1.final" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\DotNetCore.CAP.Dashboard\DotNetCore.CAP.Dashboard.csproj" />
<ProjectReference Include="..\..\src\DotNetCore.CAP.MySql\DotNetCore.CAP.MySql.csproj" />
<ProjectReference Include="..\..\src\DotNetCore.CAP.RabbitMQ\DotNetCore.CAP.RabbitMQ.csproj" />
<ProjectReference Include="..\..\src\DotNetCore.CAP\DotNetCore.CAP.csproj" />
......
......@@ -15,7 +15,7 @@ namespace Sample.RabbitMQ.MySql
{
x.UseEntityFramework<AppDbContext>();
x.UseRabbitMQ("192.168.2.120");
//x.UseDashboard();
x.UseDashboard();
x.FailedRetryCount = 5;
x.FailedThresholdCallback = (type, msg) =>
{
......
// Copyright (c) .NET Core Community. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
using System;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace Microsoft.Extensions.Internal
{
internal struct AwaitableInfo
{
public Type AwaiterType { get; }
public PropertyInfo AwaiterIsCompletedProperty { get; }
public MethodInfo AwaiterGetResultMethod { get; }
public MethodInfo AwaiterOnCompletedMethod { get; }
public MethodInfo AwaiterUnsafeOnCompletedMethod { get; }
public Type ResultType { get; }
public MethodInfo GetAwaiterMethod { get; }
public AwaitableInfo(
Type awaiterType,
PropertyInfo awaiterIsCompletedProperty,
MethodInfo awaiterGetResultMethod,
MethodInfo awaiterOnCompletedMethod,
MethodInfo awaiterUnsafeOnCompletedMethod,
Type resultType,
MethodInfo getAwaiterMethod)
{
AwaiterType = awaiterType;
AwaiterIsCompletedProperty = awaiterIsCompletedProperty;
AwaiterGetResultMethod = awaiterGetResultMethod;
AwaiterOnCompletedMethod = awaiterOnCompletedMethod;
AwaiterUnsafeOnCompletedMethod = awaiterUnsafeOnCompletedMethod;
ResultType = resultType;
GetAwaiterMethod = getAwaiterMethod;
}
public static bool IsTypeAwaitable(Type type, out AwaitableInfo awaitableInfo)
{
// Based on Roslyn code: http://source.roslyn.io/#Microsoft.CodeAnalysis.Workspaces/Shared/Extensions/ISymbolExtensions.cs,db4d48ba694b9347
// Awaitable must have method matching "object GetAwaiter()"
var getAwaiterMethod = type.GetRuntimeMethods().FirstOrDefault(m =>
m.Name.Equals("GetAwaiter", StringComparison.OrdinalIgnoreCase)
&& m.GetParameters().Length == 0
&& m.ReturnType != null);
if (getAwaiterMethod == null)
{
awaitableInfo = default(AwaitableInfo);
return false;
}
var awaiterType = getAwaiterMethod.ReturnType;
// Awaiter must have property matching "bool IsCompleted { get; }"
var isCompletedProperty = awaiterType.GetRuntimeProperties().FirstOrDefault(p =>
p.Name.Equals("IsCompleted", StringComparison.OrdinalIgnoreCase)
&& p.PropertyType == typeof(bool)
&& p.GetMethod != null);
if (isCompletedProperty == null)
{
awaitableInfo = default(AwaitableInfo);
return false;
}
// Awaiter must implement INotifyCompletion
var awaiterInterfaces = awaiterType.GetInterfaces();
var implementsINotifyCompletion = awaiterInterfaces.Any(t => t == typeof(INotifyCompletion));
if (!implementsINotifyCompletion)
{
awaitableInfo = default(AwaitableInfo);
return false;
}
// INotifyCompletion supplies a method matching "void OnCompleted(Action action)"
var iNotifyCompletionMap = awaiterType
.GetTypeInfo()
.GetRuntimeInterfaceMap(typeof(INotifyCompletion));
var onCompletedMethod = iNotifyCompletionMap.InterfaceMethods.Single(m =>
m.Name.Equals("OnCompleted", StringComparison.OrdinalIgnoreCase)
&& m.ReturnType == typeof(void)
&& m.GetParameters().Length == 1
&& m.GetParameters()[0].ParameterType == typeof(Action));
// Awaiter optionally implements ICriticalNotifyCompletion
var implementsICriticalNotifyCompletion =
awaiterInterfaces.Any(t => t == typeof(ICriticalNotifyCompletion));
MethodInfo unsafeOnCompletedMethod;
if (implementsICriticalNotifyCompletion)
{
// ICriticalNotifyCompletion supplies a method matching "void UnsafeOnCompleted(Action action)"
var iCriticalNotifyCompletionMap = awaiterType
.GetTypeInfo()
.GetRuntimeInterfaceMap(typeof(ICriticalNotifyCompletion));
unsafeOnCompletedMethod = iCriticalNotifyCompletionMap.InterfaceMethods.Single(m =>
m.Name.Equals("UnsafeOnCompleted", StringComparison.OrdinalIgnoreCase)
&& m.ReturnType == typeof(void)
&& m.GetParameters().Length == 1
&& m.GetParameters()[0].ParameterType == typeof(Action));
}
else
{
unsafeOnCompletedMethod = null;
}
// Awaiter must have method matching "void GetResult" or "T GetResult()"
var getResultMethod = awaiterType.GetRuntimeMethods().FirstOrDefault(m =>
m.Name.Equals("GetResult")
&& m.GetParameters().Length == 0);
if (getResultMethod == null)
{
awaitableInfo = default(AwaitableInfo);
return false;
}
awaitableInfo = new AwaitableInfo(
awaiterType,
isCompletedProperty,
getResultMethod,
onCompletedMethod,
unsafeOnCompletedMethod,
getResultMethod.ReturnType,
getAwaiterMethod);
return true;
}
}
}
\ No newline at end of file
......@@ -6,19 +6,89 @@ using System.Linq;
using System.Net;
using System.Threading.Tasks;
using DotNetCore.CAP.Dashboard;
using DotNetCore.CAP.Dashboard.GatewayProxy;
using DotNetCore.CAP.Dashboard.NodeDiscovery;
using DotNetCore.CAP.Persistence;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
// ReSharper disable once CheckNamespace
namespace DotNetCore.CAP
{
public static class CapBuilderExtension
{
public static IApplicationBuilder UseCapDashboard(this IApplicationBuilder app)
{
if (app == null)
{
throw new ArgumentNullException(nameof(app));
}
CheckRequirement(app);
var provider = app.ApplicationServices;
if (provider.GetService<DashboardOptions>() != null)
{
if (provider.GetService<DiscoveryOptions>() != null)
{
app.UseMiddleware<GatewayProxyMiddleware>();
}
app.UseMiddleware<DashboardMiddleware>();
}
return app;
}
private static void CheckRequirement(IApplicationBuilder app)
{
var marker = app.ApplicationServices.GetService<CapMarkerService>();
if (marker == null)
{
throw new InvalidOperationException(
"AddCap() must be called on the service collection. eg: services.AddCap(...)");
}
var messageQueueMarker = app.ApplicationServices.GetService<CapMessageQueueMakerService>();
if (messageQueueMarker == null)
{
throw new InvalidOperationException(
"You must be config used message queue provider at AddCap() options! eg: services.AddCap(options=>{ options.UseKafka(...) })");
}
var databaseMarker = app.ApplicationServices.GetService<CapStorageMarkerService>();
if (databaseMarker == null)
{
throw new InvalidOperationException(
"You must be config used database provider at AddCap() options! eg: services.AddCap(options=>{ options.UseSqlServer(...) })");
}
}
}
sealed class CapStartupFilter : IStartupFilter
{
public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
{
return app =>
{
app.UseCapDashboard();
next(app);
};
}
}
public class DashboardMiddleware
{
private readonly RequestDelegate _next;
private readonly DashboardOptions _options;
private readonly RouteCollection _routes;
private readonly IStorage _storage;
private readonly IDataStorage _storage;
public DashboardMiddleware(RequestDelegate next, DashboardOptions options, IStorage storage,
public DashboardMiddleware(RequestDelegate next, DashboardOptions options, IDataStorage storage,
RouteCollection routes)
{
_next = next ?? throw new ArgumentNullException(nameof(next));
......
......@@ -6,6 +6,7 @@ using DotNetCore.CAP;
using DotNetCore.CAP.Dashboard;
using DotNetCore.CAP.Dashboard.GatewayProxy;
using DotNetCore.CAP.Dashboard.GatewayProxy.Requester;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
namespace DotNetCore.CAP
......@@ -23,11 +24,13 @@ namespace DotNetCore.CAP
{
var dashboardOptions = new DashboardOptions();
_options?.Invoke(dashboardOptions);
services.AddTransient<IStartupFilter, CapStartupFilter>();
services.AddSingleton(dashboardOptions);
services.AddSingleton(DashboardRoutes.Routes);
services.AddSingleton<IHttpRequester, HttpClientHttpRequester>();
services.AddSingleton<IHttpClientCache, MemoryHttpClientCache>();
services.AddSingleton<IRequestMapper, RequestMapper>();
}
}
}
......
This diff is collapsed.
// Copyright (c) .NET Core Community. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
using System;
using System.Linq.Expressions;
using Microsoft.Extensions.Internal;
namespace DotNetCore.CAP.Dashboard
{
internal struct CoercedAwaitableInfo
{
public AwaitableInfo AwaitableInfo { get; }
public Expression CoercerExpression { get; }
public Type CoercerResultType { get; }
public bool RequiresCoercion => CoercerExpression != null;
public CoercedAwaitableInfo(AwaitableInfo awaitableInfo)
{
AwaitableInfo = awaitableInfo;
CoercerExpression = null;
CoercerResultType = null;
}
public CoercedAwaitableInfo(Expression coercerExpression, Type coercerResultType,
AwaitableInfo coercedAwaitableInfo)
{
CoercerExpression = coercerExpression;
CoercerResultType = coercerResultType;
AwaitableInfo = coercedAwaitableInfo;
}
public static bool IsTypeAwaitable(Type type, out CoercedAwaitableInfo info)
{
if (AwaitableInfo.IsTypeAwaitable(type, out var directlyAwaitableInfo))
{
info = new CoercedAwaitableInfo(directlyAwaitableInfo);
return true;
}
info = default(CoercedAwaitableInfo);
return false;
}
}
}
\ No newline at end of file
......@@ -2,6 +2,7 @@
// Licensed under the MIT License. See License.txt in the project root for license information.
using System.Reflection;
using System.Threading.Tasks;
namespace DotNetCore.CAP.Dashboard
{
......@@ -22,14 +23,14 @@ namespace DotNetCore.CAP.Dashboard
_resourceNames = resourceNames;
}
protected override void WriteResponse(DashboardResponse response)
protected override async Task WriteResponse(DashboardResponse response)
{
foreach (var resourceName in _resourceNames)
{
WriteResource(
response,
_assembly,
$"{_baseNamespace}.{resourceName}");
await WriteResource(
response,
_assembly,
$"{_baseNamespace}.{resourceName}");
}
}
}
......
......@@ -3,13 +3,14 @@
using System;
using System.Text.RegularExpressions;
using DotNetCore.CAP.Persistence;
using Microsoft.AspNetCore.Http;
namespace DotNetCore.CAP.Dashboard
{
public abstract class DashboardContext
{
protected DashboardContext(IStorage storage, DashboardOptions options)
protected DashboardContext(IDataStorage storage, DashboardOptions options)
{
if (storage == null)
{
......@@ -25,7 +26,7 @@ namespace DotNetCore.CAP.Dashboard
Options = options;
}
public IStorage Storage { get; }
public IDataStorage Storage { get; }
public DashboardOptions Options { get; }
......@@ -41,7 +42,7 @@ namespace DotNetCore.CAP.Dashboard
public sealed class CapDashboardContext : DashboardContext
{
public CapDashboardContext(
IStorage storage,
IDataStorage storage,
DashboardOptions options,
HttpContext httpContext)
: base(storage, options)
......
......@@ -83,14 +83,14 @@ namespace DotNetCore.CAP.Dashboard
Routes.AddJsonResult("/published/message/(?<Id>.+)", x =>
{
var id = long.Parse(x.UriMatch.Groups["Id"].Value);
var message = x.Storage.GetConnection().GetPublishedMessageAsync(id)
var message = x.Storage.GetMonitoringApi().GetPublishedMessageAsync(id)
.GetAwaiter().GetResult();
return message.Content;
});
Routes.AddJsonResult("/received/message/(?<Id>.+)", x =>
{
var id = long.Parse(x.UriMatch.Groups["Id"].Value);
var message = x.Storage.GetConnection().GetReceivedMessageAsync(id)
var message = x.Storage.GetMonitoringApi().GetReceivedMessageAsync(id)
.GetAwaiter().GetResult();
return message.Content;
});
......@@ -99,7 +99,7 @@ namespace DotNetCore.CAP.Dashboard
"/published/requeue",
(client, messageId) =>
{
var msg = client.Storage.GetConnection().GetPublishedMessageAsync(messageId)
var msg = client.Storage.GetMonitoringApi().GetPublishedMessageAsync(messageId)
.GetAwaiter().GetResult();
client.RequestServices.GetService<IDispatcher>().EnqueueToPublish(msg);
});
......@@ -107,9 +107,9 @@ namespace DotNetCore.CAP.Dashboard
"/received/requeue",
(client, messageId) =>
{
var msg = client.Storage.GetConnection().GetReceivedMessageAsync(messageId)
var msg = client.Storage.GetMonitoringApi().GetReceivedMessageAsync(messageId)
.GetAwaiter().GetResult();
client.RequestServices.GetService<IDispatcher>().EnqueueToExecute(msg);
client.RequestServices.GetService<ISubscriberExecutor>().ExecuteAsync(msg);
});
Routes.AddRazorPage(
......
......@@ -30,22 +30,20 @@ namespace DotNetCore.CAP.Dashboard
}
}
public Task Dispatch(DashboardContext context)
public async Task Dispatch(DashboardContext context)
{
context.Response.ContentType = _contentType;
context.Response.SetExpire(DateTimeOffset.Now.AddYears(1));
WriteResponse(context.Response);
return Task.FromResult(true);
await WriteResponse(context.Response);
}
protected virtual void WriteResponse(DashboardResponse response)
protected virtual Task WriteResponse(DashboardResponse response)
{
WriteResource(response, _assembly, _resourceName);
return WriteResource(response, _assembly, _resourceName);
}
protected void WriteResource(DashboardResponse response, Assembly assembly, string resourceName)
protected async Task WriteResource(DashboardResponse response, Assembly assembly, string resourceName)
{
using (var inputStream = assembly.GetManifestResourceStream(resourceName))
{
......@@ -54,8 +52,7 @@ namespace DotNetCore.CAP.Dashboard
throw new ArgumentException(
$@"Resource with name {resourceName} not found in assembly {assembly}.");
}
inputStream.CopyTo(response.Body);
await inputStream.CopyToAsync(response.Body);
}
}
}
......
......@@ -9,7 +9,7 @@ using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using DotNetCore.CAP.Dashboard.GatewayProxy.Requester;
using DotNetCore.CAP.NodeDiscovery;
using DotNetCore.CAP.Dashboard.NodeDiscovery;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Primitives;
......
......@@ -10,7 +10,7 @@ using System.Text;
using System.Text.RegularExpressions;
using DotNetCore.CAP.Dashboard.Pages;
using DotNetCore.CAP.Dashboard.Resources;
using DotNetCore.CAP.Infrastructure;
using DotNetCore.CAP.Internal;
using DotNetCore.CAP.Messages;
using Microsoft.Extensions.Internal;
......
......@@ -38,7 +38,7 @@ namespace DotNetCore.CAP.Dashboard
{
new StringEnumConverter
{
NamingStrategy = new CamelCaseNamingStrategy()
CamelCaseText= true
}
}
};
......
......@@ -34,7 +34,7 @@ namespace DotNetCore.CAP.Dashboard
{
new StringEnumConverter
{
NamingStrategy = new CamelCaseNamingStrategy()
CamelCaseText = true
}
}
};
......@@ -46,7 +46,7 @@ namespace DotNetCore.CAP.Dashboard
private class StubPage : RazorPage
{
protected override void Execute()
public override void Execute()
{
}
}
......
// Copyright (c) .NET Core Community. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
using DotNetCore.CAP.Infrastructure;
using DotNetCore.CAP.Internal;
namespace DotNetCore.CAP.Dashboard
{
......
......@@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Net;
using System.Text;
using DotNetCore.CAP.Infrastructure;
using DotNetCore.CAP.Internal;
namespace DotNetCore.CAP.Dashboard
{
......@@ -24,16 +24,16 @@ namespace DotNetCore.CAP.Dashboard
[SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline")]
static MessageHistoryRenderer()
{
Register(StatusName.Succeeded, SucceededRenderer);
Register(StatusName.Failed, FailedRenderer);
Register(nameof(StatusName.Succeeded), SucceededRenderer);
Register(nameof(StatusName.Failed), FailedRenderer);
BackgroundStateColors.Add(StatusName.Succeeded, "#EDF7ED");
BackgroundStateColors.Add(StatusName.Failed, "#FAEBEA");
BackgroundStateColors.Add(StatusName.Scheduled, "#E0F3F8");
BackgroundStateColors.Add(nameof(StatusName.Succeeded), "#EDF7ED");
BackgroundStateColors.Add(nameof(StatusName.Failed), "#FAEBEA");
BackgroundStateColors.Add(nameof(StatusName.Scheduled), "#E0F3F8");
ForegroundStateColors.Add(StatusName.Succeeded, "#5cb85c");
ForegroundStateColors.Add(StatusName.Failed, "#d9534f");
ForegroundStateColors.Add(StatusName.Scheduled, "#5bc0de");
ForegroundStateColors.Add(nameof(StatusName.Succeeded), "#5cb85c");
ForegroundStateColors.Add(nameof(StatusName.Failed), "#d9534f");
ForegroundStateColors.Add(nameof(StatusName.Scheduled), "#5bc0de");
}
public static void AddBackgroundStateColor(string stateName, string color)
......
......@@ -7,9 +7,9 @@ namespace DotNetCore.CAP.Dashboard.Pages
{
public BlockMetric(DashboardMetric dashboardMetric)
{
DashboardMetric = dashboardMetric;
Metric = dashboardMetric;
}
public DashboardMetric DashboardMetric { get; }
public DashboardMetric Metric { get; }
}
}
\ No newline at end of file
......@@ -2,7 +2,7 @@
// Licensed under the MIT License. See License.txt in the project root for license information.
using System.Collections.Generic;
using DotNetCore.CAP.NodeDiscovery;
using DotNetCore.CAP.Dashboard.NodeDiscovery;
using Microsoft.Extensions.DependencyInjection;
namespace DotNetCore.CAP.Dashboard.Pages
......
......@@ -2,21 +2,22 @@
// Licensed under the MIT License. See License.txt in the project root for license information.
using System;
using DotNetCore.CAP.Monitoring;
namespace DotNetCore.CAP.Dashboard.Pages
{
internal partial class PublishedPage
internal partial class PublishedPage : DotNetCore.CAP.Dashboard.RazorPage
{
public PublishedPage(string statusName)
{
StatusName = statusName;
Name = statusName;
}
public string StatusName { get; set; }
public string Name { get; set; }
public int GetTotal(IMonitoringApi api)
{
if (string.Equals(StatusName, Infrastructure.StatusName.Succeeded,
if (string.Equals(Name, nameof(Internal.StatusName.Succeeded),
StringComparison.CurrentCultureIgnoreCase))
{
return api.PublishedSucceededCount();
......
@* Generator: Template TypeVisibility: Internal GeneratePrettyNames: True *@
@using System
@using DotNetCore.CAP.Dashboard
@using DotNetCore.CAP.Dashboard.Monitoring
@using DotNetCore.CAP.Dashboard.Pages
@using DotNetCore.CAP.Dashboard.Resources
@using DotNetCore.CAP.Messages
@using DotNetCore.CAP.Monitoring
@inherits DotNetCore.CAP.Dashboard.RazorPage
@{
Layout = new LayoutPage(Strings.PublishedMessagesPage_Title);
......@@ -23,7 +23,7 @@
MessageType = MessageType.Publish,
Name = name,
Content = content,
StatusName = StatusName,
StatusName = Name,
CurrentPage = pager.CurrentPage - 1,
PageSize = pager.RecordsPerPage
};
......@@ -84,7 +84,7 @@
<th>@Strings.Common_Version</th>
<th>@Strings.MessagesPage_Table_Name</th>
<th class="min-width">@Strings.MessagesPage_Table_Retries</th>
@if (string.Equals(StatusName, "Processing", StringComparison.CurrentCultureIgnoreCase))
@if (string.Equals(Name, "Processing", StringComparison.CurrentCultureIgnoreCase))
{
<th>@Strings.MessagesPage_Table_State</th>
}
......@@ -110,7 +110,7 @@
<td>
@message.Retries
</td>
@if (string.Equals(StatusName, "Processing", StringComparison.CurrentCultureIgnoreCase))
@if (string.Equals(Name, "Processing", StringComparison.CurrentCultureIgnoreCase))
{
<td>
@message.StatusName
......
......@@ -2,6 +2,7 @@
// Licensed under the MIT License. See License.txt in the project root for license information.
using System;
using DotNetCore.CAP.Monitoring;
namespace DotNetCore.CAP.Dashboard.Pages
{
......@@ -16,7 +17,7 @@ namespace DotNetCore.CAP.Dashboard.Pages
public int GetTotal(IMonitoringApi api)
{
if (string.Equals(StatusName, Infrastructure.StatusName.Succeeded,
if (string.Equals(StatusName, nameof(Internal.StatusName.Succeeded),
StringComparison.CurrentCultureIgnoreCase))
{
return api.ReceivedSucceededCount();
......
@* Generator: Template TypeVisibility: Internal GeneratePrettyNames: True *@
@using System
@using DotNetCore.CAP.Dashboard
@using DotNetCore.CAP.Dashboard.Monitoring
@using DotNetCore.CAP.Dashboard.Pages
@using DotNetCore.CAP.Dashboard.Resources
@using DotNetCore.CAP.Messages
@using DotNetCore.CAP.Monitoring
@inherits DotNetCore.CAP.Dashboard.RazorPage
@{
Layout = new LayoutPage(Strings.ReceivedMessagesPage_Title);
......
@* Generator: Template TypeVisibility: Internal GeneratePrettyNames: True TrimLeadingUnderscores : true *@
@using DotNetCore.CAP.Dashboard
@using DotNetCore.CAP.Dashboard.Resources
@inherits RazorPage
@inherits DotNetCore.CAP.Dashboard.RazorPage
@{
var metric = DashboardMetric.Func(this);
var metric = Metric.Func(this);
var className = metric == null ? "metric-null" : metric.Style.ToClassName();
var highlighted = metric != null && metric.Highlighted ? "highlighted" : null;
}
<div class="metric @className @highlighted">
<div class="metric-body" data-metric="@DashboardMetric.Name">
<div class="metric-body" data-metric="@Metric.Name">
@(metric?.Value)
</div>
<div class="metric-description">
@(Strings.ResourceManager.GetString(DashboardMetric.Title) ?? DashboardMetric.Title)
@(Strings.ResourceManager.GetString(Metric.Title) ?? Metric.Title)
</div>
</div>
\ No newline at end of file
......@@ -16,37 +16,33 @@ namespace DotNetCore.CAP.Dashboard.Pages
using System.Linq;
using System.Text;
#line 2 "..\..\Dashboard\Pages\_BlockMetric.cshtml"
using DotNetCore.CAP.Dashboard;
#line default
#line hidden
#line 3 "..\..\Dashboard\Pages\_BlockMetric.cshtml"
#line 2 "..\..\Pages\_BlockMetric.cshtml"
using DotNetCore.CAP.Dashboard.Resources;
#line default
#line hidden
[System.CodeDom.Compiler.GeneratedCodeAttribute("RazorGenerator", "2.0.0.0")]
internal partial class BlockMetric : RazorPage
internal partial class BlockMetric : DotNetCore.CAP.Dashboard.RazorPage
{
#line hidden
protected override void Execute()
public override void Execute()
{
WriteLiteral("\r\n");
WriteLiteral("\r\n");
#line 5 "..\..\Dashboard\Pages\_BlockMetric.cshtml"
#line 5 "..\..\Pages\_BlockMetric.cshtml"
var metric = DashboardMetric.Func(this);
var metric = Metric.Func(this);
var className = metric == null ? "metric-null" : metric.Style.ToClassName();
var highlighted = metric != null && metric.Highlighted ? "highlighted" : null;
......@@ -58,7 +54,7 @@ WriteLiteral("<div class=\"metric ");
#line 10 "..\..\Dashboard\Pages\_BlockMetric.cshtml"
#line 11 "..\..\Pages\_BlockMetric.cshtml"
Write(className);
......@@ -68,7 +64,7 @@ WriteLiteral(" ");
#line 10 "..\..\Dashboard\Pages\_BlockMetric.cshtml"
#line 11 "..\..\Pages\_BlockMetric.cshtml"
Write(highlighted);
......@@ -78,8 +74,8 @@ WriteLiteral("\">\r\n <div class=\"metric-body\" data-metric=\"");
#line 11 "..\..\Dashboard\Pages\_BlockMetric.cshtml"
Write(DashboardMetric.Name);
#line 12 "..\..\Pages\_BlockMetric.cshtml"
Write(Metric.Name);
#line default
......@@ -88,7 +84,7 @@ WriteLiteral("\">\r\n ");
#line 12 "..\..\Dashboard\Pages\_BlockMetric.cshtml"
#line 13 "..\..\Pages\_BlockMetric.cshtml"
Write(metric?.Value);
......@@ -98,8 +94,8 @@ WriteLiteral("\r\n </div>\r\n <div class=\"metric-description\">\r\n
#line 15 "..\..\Dashboard\Pages\_BlockMetric.cshtml"
Write(Strings.ResourceManager.GetString(DashboardMetric.Title) ?? DashboardMetric.Title);
#line 16 "..\..\Pages\_BlockMetric.cshtml"
Write(Strings.ResourceManager.GetString(Metric.Title) ?? Metric.Title);
#line default
......
......@@ -16,51 +16,45 @@ namespace DotNetCore.CAP.Dashboard.Pages
using System.Linq;
using System.Text;
#line 2 "..\..\Dashboard\Pages\_Breadcrumbs.cshtml"
using DotNetCore.CAP.Dashboard;
#line default
#line hidden
[System.CodeDom.Compiler.GeneratedCodeAttribute("RazorGenerator", "2.0.0.0")]
internal partial class Breadcrumbs : RazorPage
internal partial class Breadcrumbs : DotNetCore.CAP.Dashboard.RazorPage
{
#line hidden
protected override void Execute()
public override void Execute()
{
WriteLiteral("\r\n");
WriteLiteral("\r\n<ol class=\"breadcrumb\">\r\n <li><a href=\"");
WriteLiteral("\r\n<ol class=\"breadcrumb\">\r\n <li>\r\n <a href=\"");
#line 6 "..\..\Dashboard\Pages\_Breadcrumbs.cshtml"
#line 6 "..\..\Pages\_Breadcrumbs.cshtml"
Write(Url.Home());
#line default
#line hidden
WriteLiteral("\"><span class=\"glyphicon glyphicon-home\"></span></a></li>\r\n");
WriteLiteral("\">\r\n <span class=\"glyphicon glyphicon-home\"></span>\r\n </a>\r\n " +
" </li>\r\n");
#line 7 "..\..\Dashboard\Pages\_Breadcrumbs.cshtml"
#line 10 "..\..\Pages\_Breadcrumbs.cshtml"
foreach (var item in Items)
{
#line default
#line hidden
WriteLiteral(" <li><a href=\"");
WriteLiteral(" <li>\r\n <a href=\"");
#line 9 "..\..\Dashboard\Pages\_Breadcrumbs.cshtml"
#line 13 "..\..\Pages\_Breadcrumbs.cshtml"
Write(item.Value);
......@@ -70,17 +64,17 @@ WriteLiteral("\">");
#line 9 "..\..\Dashboard\Pages\_Breadcrumbs.cshtml"
#line 13 "..\..\Pages\_Breadcrumbs.cshtml"
Write(item.Key);
#line default
#line hidden
WriteLiteral("</a></li>\r\n");
WriteLiteral("</a>\r\n </li>\r\n");
#line 10 "..\..\Dashboard\Pages\_Breadcrumbs.cshtml"
#line 15 "..\..\Pages\_Breadcrumbs.cshtml"
}
......@@ -90,7 +84,7 @@ WriteLiteral(" <li class=\"active\">");
#line 11 "..\..\Dashboard\Pages\_Breadcrumbs.cshtml"
#line 16 "..\..\Pages\_Breadcrumbs.cshtml"
Write(Title);
......
This diff is collapsed.
......@@ -9,6 +9,14 @@ namespace DotNetCore.CAP.Internal
{
public static class Helper
{
private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local);
public static long ToTimestamp(DateTime value)
{
var elapsedTime = value - Epoch;
return (long)elapsedTime.TotalSeconds;
}
public static bool IsController(TypeInfo typeInfo)
{
if (!typeInfo.IsClass)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment