Service log

This commit is contained in:
Vincent Fiduccia 2017-05-24 14:41:35 -07:00
parent 71ae6d1d34
commit 29e7cb41b2
No known key found for this signature in database
GPG Key ID: 2B29AD6BB2BB2582
6 changed files with 327 additions and 278 deletions

View File

@ -0,0 +1,43 @@
import Ember from 'ember';
export default Ember.Component.extend({
prefs: Ember.inject.service(),
stickyHeader: true,
showHost: true,
showStats: false,
showInstanceState: true,
pagingLabel: 'pagination.entry',
sortBy: 'name',
headers: [
{
name: 'time',
sort: ['createdTs:desc','id:desc'],
searchField: 'created',
translationKey: 'serviceLog.time',
width: 150,
},
{
name: 'level',
sort: ['level','createdTs:desc','id:desc'],
translationKey: 'serviceLog.level',
width: 100,
},
{
name: 'event',
sort: ['eventType','createdTs:desc','id:desc'],
searchField: 'eventType',
translationKey: 'serviceLog.event',
width: 200,
},
{
name: 'detail',
sort: ['description','createdTs:desc','id:desc'],
searchField: 'description',
translationKey: 'serviceLog.detail',
},
],
});

View File

@ -0,0 +1,34 @@
{{#sortable-table
classNames="grid sortable-table"
body=logs
searchText=searchText
sortBy=sortBy
bulkActions=false
search=true
fullRows=true
pagingLabel="pagination.event"
headers=headers as |sortable kind row dt|}}
{{#if (eq kind "row")}}
<tr>
<td data-title="{{dt.time}}">
{{date-str row.created format="hh:mm:ss A"}}
</td>
<td data-title="{{dt.level}}">
<span class="state badge-sm {{row.stateColor}} {{row.stateBackground}}">{{upper-case row.level}}</span>
</td>
<td data-title="{{dt.event}}">
{{row.eventType}}{{#if row.runTime}} ({{row.runTime}}){{/if}}
</td>
<td data-title="{{dt.detail}}">
{{row.description}}
</td>
<td data-title="{{dt.actions}}" class="actions">
{{action-menu model=row}}
</td>
</tr>
{{else if (eq kind "nomatch")}}
<tr><td colspan="{{sortable.fullColspan}}" class="text-center text-muted p-20">{{t 'containersPage.table.noMatch'}}</td></tr>
{{else if (eq kind "norows")}}
<tr><td colspan="{{sortable.fullColspan}}" class="text-center text-muted p-20">{{t 'containersPage.table.noData'}}</td></tr>
{{/if}}
{{/sortable-table}}

View File

@ -58,8 +58,6 @@
</tr> </tr>
{{else if (eq kind "nomatch")}} {{else if (eq kind "nomatch")}}
<tr><td colspan="{{sortable.fullColspan}}" class="text-center text-muted lacsso pt-20 pb-20">{{t 'containersPage.table.noMatch'}}</td></tr> <tr><td colspan="{{sortable.fullColspan}}" class="text-center text-muted lacsso pt-20 pb-20">{{t 'containersPage.table.noMatch'}}</td></tr>
{{else if (eq kind "norows")}}
<tr><td colspan="{{sortable.fullColspan}}" class="text-center text-muted lacsso pt-20 pb-20">{{t 'containersPage.table.noMatch'}}</td></tr>
{{/if}} {{/if}}
{{/sortable-table}} {{/sortable-table}}
{{else}} {{else}}

View File

@ -22,7 +22,7 @@
{{!todo copy pasta}} {{!todo copy pasta}}
<section> <section>
<div class="row banner bg-info basics "> <div class="row banner bg-info basics">
{{#if service.launchConfig.memoryReservation}} {{#if service.launchConfig.memoryReservation}}
<div class="inline-block"> <div class="inline-block">
@ -67,45 +67,210 @@
{{/if}} {{/if}}
</div> </div>
</section> </section>
<section> <section>
{{#accordion-list as |al expandFn| }} {{#accordion-list as |al expandFn| }}
<div class="row"> {{#if (eq service.kind 'externalService')}}
<div class="col span-12"> {{!-- since external services are the only ones that have externalIp/hostname it didnt make sense to give extIps its own route like other services --}}
{{#if (eq service.kind 'externalService')}} <hr/>
{{!-- since external services are the only ones that have externalIp/hostname it didnt make sense to give extIps its own route like other services --}} <section>
<hr/> <div>
<section> {{#if service.externalIpAddresses}}
<div> <label class="text-muted ml-15">{{t 'servicePage.external.externalIp'}}</label>
{{#if service.externalIpAddresses}} <ul class="list-unstyled list-inline with-room">
<label class="text-muted ml-15">{{t 'servicePage.external.externalIp'}}</label> {{#each service.externalIpAddresses as |ip|}}
<ul class="list-unstyled list-inline with-room"> <li>
{{#each service.externalIpAddresses as |ip|}} <i class="icon icon-external-link"></i> {{ip}}
<li> </li>
<i class="icon icon-external-link"></i> {{ip}} {{/each}}
</li> </ul>
{{/each}} {{else}}
</ul> <label class="text-muted">{{t 'servicePage.external.externalHostname'}} </label> {{service.hostname}}
{{else}} {{/if}}
<label class="text-muted">{{t 'servicePage.external.externalHostname'}} </label> {{service.hostname}} </div>
{{/if}} </section>
</div> <hr/>
</section> {{/if}}
<hr/>
{{/if}}
{{#accordion-list-item {{#if service.canHaveContainers}}
title=(t 'servicePage.portsTab.title') {{#accordion-list-item
detail=(t 'servicePage.portsTab.detail') title=(t 'servicePage.containersTab.title')
status=(t 'servicePage.portsTab.status' count=model.service.endpointsByPort.length) detail=(t 'servicePage.containersTab.detail')
statusClass=(if model.service.endpointsByPort.length 'bg-success' 'text-muted') status=(t 'servicePage.containersTab.status' count=service.instances.length)
expandAll=al.expandAll statusClass=(if service.instances.length 'bg-success' 'text-muted')
expand=(action expandFn) expanded=true
expandAll=al.expandAll
expand=(action expandFn)
componentName='container-table'
as | parent |
}}
{{component parent.intent
body=service.instances
bulkActions=true
showHost=true
}} }}
{{#if model.service.isActive}} {{/accordion-list-item}}
<!--ports start--> {{/if}}
{{#if service.isBalancer}}
{{#accordion-list-item
title=(t 'formBalancerRules.label')
detail=(t 'formBalancerRules.detail')
status=(t 'formBalancerRules.status' count=(if rules.length rules.length 0))
statusClass=(if rules.length 'bg-success' 'text-muted')
expandAll=al.expandAll
expand=(action expandFn)
}}
{{#if rules.length}}
<table class="grid fixed no-lines no-top-padding tight mb-0">
<thead>
<tr>
<th width="65">{{t 'formBalancerRules.priority.label'}}</th>
<th width="60">{{t 'formBalancerRules.access.label'}}</th>
<th width="70">{{t 'formBalancerRules.protocol.label'}}</th>
<th class="divided">{{t 'formBalancerRules.hostname.label'}}</th>
<th width="60">{{t 'formBalancerRules.sourcePort.label'}}</th>
<th>{{t 'formBalancerRules.path.label'}}</th>
<th class="divided">{{t 'formBalancerRules.target'}}</th>
<th width="60">{{t 'formBalancerRules.targetPort.label'}}</th>
<th class="divided">{{t 'formBalancerRules.backendName.label'}}</th>
</tr>
</thead>
{{#each model.service.endpointsByPort as |obj|}} <tbody>
{{#each rules as |rule idx|}}
<tr>
<td data-title="{{t 'formBalancerRules.priority.label'}}">
{{rule.priority}}
</td>
<td data-title="{{t 'formBalancerRules.access.label'}}">
{{uc-first rule.access}}
</td>
<td data-title="{{t 'formBalancerRules.protocol.label'}}">
{{upper-case rule.protocol}}
</td>
<td class="divided" data-title="{{t 'formBalancerRules.hostname.label'}}">
{{#if rule.canHostname}}
{{#if rule.hostname}}
{{rule.hostname}}
{{else}}
<span class="text-muted">{{t 'generic.none'}}</span>
{{/if}}
{{else}}
<span class="text-muted">{{t 'generic.na'}}</span>
{{/if}}
</td>
<td data-title="{{t 'formBalancerRules.sourcePort.label'}}">
{{rule.sourcePort}}
</td>
<td data-title="{{t 'formBalancerRules.path.label'}}">
{{#if rule.canPath}}
{{#if rule.path}}
{{rule.path}}
{{else}}
<span class="text-muted">{{t 'generic.none'}}</span>
{{/if}}
{{else}}
<span class="text-muted">{{t 'generic.na'}}</span>
{{/if}}
</td>
<td class="divided" data-title="{{t (if rule.isSelector 'formBalancerRules.selector.label' 'formBalancerRules.serviceId.label')}}">
{{#if rule.selector}}
{{rule.selector}}
{{else}}
<a href="{{href-to "service" rule.serviceId}}">
{{#if (not-eq service.stackId rule.service.stackId)~}}
{{rule.service.displayStack}}/
{{~/if~}}
{{~rule.service.displayName~}}
</a>
{{~/if~}}
</td>
<td data-title="{{t 'formBalancerRules.targetPort.label'}}">
{{rule.targetPort}}
</td>
<td class="divided" data-title="{{t 'formBalancerRules.backendName.label'}}">
{{#if rule.backendName}}
{{rule.backendName}}
{{else}}
<span class="text-muted">{{t 'generic.none'}}</span>
{{/if}}
</td>
</tr>
{{/each}}
</tbody>
</table>
{{else}}
<div class="text-muted text-center">{{t 'formBalancerRules.noRules'}}</div>
{{/if}}
{{/accordion-list-item}}
{{#accordion-list-item
title=(t 'servicePage.certsTab.title')
detail=(t 'servicePage.certsTab.detail')
status=(t 'servicePage.certsTab.status' count=(if model.service.lbConfig.certificateIds.length model.service.lbConfig.certificateIds.length 0))
statusClass=(if model.service.lbConfig.certificateIds.length 'bg-success' 'text-muted')
expandAll=al.expandAll
expand=(action expandFn)
}}
<div class="row">
<div class="box col span-6">
<label class="acc-label">{{t 'servicePage.certsTab.default'}}:</label>
{{#if model.service.lbConfig.defaultCertificateId}}
<a href="{{href-to "certificates.detail" model.service.lbConfig.defaultCertificateId}}">{{model.service.lbConfig.defaultCertificate.displayName}}</a>
{{else}}
<div class="text-muted">{{t 'generic.none'}}</div>
{{/if}}
</div>
<div class="box col span-6">
<label class="acc-label">{{t 'servicePage.certsTab.additional'}}:</label>
{{#if model.service.lbConfig.certificateIds.length}}
<ul class="list-unstyled">
{{#each model.service.lbConfig.certificates as |cert|}}
<li>
<a href="{{href-to "certificates.detail" cert.id}}">{{cert.displayName}}</a>
</li>
{{/each}}
</ul>
{{else}}
<div class="text-muted">{{t 'generic.none'}}</div>
{{/if}}
</div>
</div>
{{/accordion-list-item}}
{{/if}}
{{#if (and service.isReal (not service.isBalancer))}}
{{container/form-command
tagName=''
instance=service
isService=true
initialLabels=service.launchConfig.labels
editing=false
expandAll=al.expandAll
expandFn=expandFn
}}
{{/if}}
{{#if service.hasPorts}}
{{#accordion-list-item
title=(t 'servicePage.portsTab.title')
detail=(t 'servicePage.portsTab.detail')
status=(t 'servicePage.portsTab.status' count=service.endpointsByPort.length)
statusClass=(if service.endpointsByPort.length 'bg-success' 'text-muted')
expandAll=al.expandAll
expand=(action expandFn)
}}
{{#if service.isActive}}
{{#each model.service.endpointsByPort as |obj|}}
<div class="row box mb-10"> <div class="row box mb-10">
<div class="col span-2"> <div class="col span-2">
<label class="acc-label">{{t 'servicePage.portsTab.table.header.port'}}</label> <label class="acc-label">{{t 'servicePage.portsTab.table.header.port'}}</label>
@ -121,249 +286,44 @@
</div> </div>
</div> </div>
</div> </div>
{{else}}
<div class="text-muted text-center">{{t 'servicePage.portsTab.table.body.noData'}}</div>
{{/each}}
<!--ports end-->
{{else}} {{else}}
<div class="text-center text-muted">{{t 'servicePage.portsTab.notActive'}}</div> <div class="text-muted text-center">{{t 'servicePage.portsTab.table.body.noData'}}</div>
{{/if}} {{/each}}
{{/accordion-list-item}} {{else}}
<div class="text-center text-muted">{{t 'servicePage.portsTab.notActive'}}</div>
{{/if}}
{{/accordion-list-item}}
{{/if}}
{{#accordion-list-item {{labels-section model=service.launchConfig tagName='' expandAll=al.expandAll expandFn=expandFn}}
title=(t 'formBalancerRules.label')
detail=(t 'formBalancerRules.detail')
status=(t 'formBalancerRules.status' count=(if rules.length rules.length 0))
statusClass=(if rules.length 'bg-success' 'text-muted')
expandAll=al.expandAll
expand=(action expandFn)
}}
{{#if rules.length}}
<table class="grid fixed no-lines no-top-padding tight mb-0">
<thead>
<tr>
<th width="65">{{t 'formBalancerRules.priority.label'}}</th>
<th width="60">{{t 'formBalancerRules.access.label'}}</th>
<th width="70">{{t 'formBalancerRules.protocol.label'}}</th>
<th class="divided">{{t 'formBalancerRules.hostname.label'}}</th>
<th width="60">{{t 'formBalancerRules.sourcePort.label'}}</th>
<th>{{t 'formBalancerRules.path.label'}}</th>
<th class="divided">{{t 'formBalancerRules.target'}}</th>
<th width="60">{{t 'formBalancerRules.targetPort.label'}}</th>
<th class="divided">{{t 'formBalancerRules.backendName.label'}}</th>
</tr>
</thead>
<tbody> {{#accordion-list-item
{{#each rules as |rule idx|}} title=(t 'servicePage.linksTab.header')
<tr> detail=(t 'servicePage.linksTab.detail')
<td data-title="{{t 'formBalancerRules.priority.label'}}"> status=(t 'servicePage.linksTab.status' count=service.consumedServicesWithNames.length)
{{rule.priority}} statusClass=(if service.consumedServicesWithNames.length 'bg-success' 'text-muted')
</td> expandAll=al.expandAll
expand=(action expandFn)
}}
<label class="acc-label">{{t 'servicePage.linksTab.header'}}</label>
<ul class="list-unstyled list-inline with-room">
{{#each service.consumedServicesWithNames as |link|}}
<li>{{consumed-service-link link=link stackId=service.stackId}}</li>
{{else}}
<li class="text-muted">{{t 'servicePage.linksTab.noData'}}</li>
{{/each}}
</ul>
{{/accordion-list-item}}
<td data-title="{{t 'formBalancerRules.access.label'}}"> {{#accordion-list-item
{{uc-first rule.access}} title=(t 'servicePage.logTab.title')
</td> detail=(t 'servicePage.logTab.detail')
status=(t 'servicePage.logTab.status' count=model.logs.arrangedContent.length)
<td data-title="{{t 'formBalancerRules.protocol.label'}}"> statusClass=(if model.logs.arrangedContent.length 'bg-success' 'text-muted')
{{upper-case rule.protocol}} expandAll=al.expandAll
</td> expand=(action expandFn)
}}
<td class="divided" data-title="{{t 'formBalancerRules.hostname.label'}}"> {{service-log logs=model.logs.arrangedContent}}
{{#if rule.canHostname}} {{/accordion-list-item}}
{{#if rule.hostname}}
{{rule.hostname}}
{{else}}
<span class="text-muted">{{t 'generic.none'}}</span>
{{/if}}
{{else}}
<span class="text-muted">{{t 'generic.na'}}</span>
{{/if}}
</td>
<td data-title="{{t 'formBalancerRules.sourcePort.label'}}">
{{rule.sourcePort}}
</td>
<td data-title="{{t 'formBalancerRules.path.label'}}">
{{#if rule.canPath}}
{{#if rule.path}}
{{rule.path}}
{{else}}
<span class="text-muted">{{t 'generic.none'}}</span>
{{/if}}
{{else}}
<span class="text-muted">{{t 'generic.na'}}</span>
{{/if}}
</td>
<td class="divided" data-title="{{t (if rule.isSelector 'formBalancerRules.selector.label' 'formBalancerRules.serviceId.label')}}">
{{#if rule.selector}}
{{rule.selector}}
{{else}}
<a href="{{href-to "service" rule.serviceId}}">
{{#if (not-eq service.stackId rule.service.stackId)~}}
{{rule.service.displayStack}}/
{{~/if~}}
{{~rule.service.displayName~}}
</a>
{{~/if~}}
</td>
<td data-title="{{t 'formBalancerRules.targetPort.label'}}">
{{rule.targetPort}}
</td>
<td class="divided" data-title="{{t 'formBalancerRules.backendName.label'}}">
{{#if rule.backendName}}
{{rule.backendName}}
{{else}}
<span class="text-muted">{{t 'generic.none'}}</span>
{{/if}}
</td>
</tr>
{{/each}}
</tbody>
</table>
{{else}}
<div class="text-muted text-center">{{t 'formBalancerRules.noRules'}}</div>
{{/if}}
{{/accordion-list-item}}
{{#accordion-list-item
title=(t 'servicePage.certsTab.title')
detail=(t 'servicePage.certsTab.detail')
status=(t 'servicePage.certsTab.status' count=(if model.service.lbConfig.certificateIds.length model.service.lbConfig.certificateIds.length 0))
statusClass=(if model.service.lbConfig.certificateIds.length 'bg-success' 'text-muted')
expandAll=al.expandAll
expand=(action expandFn)
}}
<div class="row">
<div class="box col span-6">
<label class="acc-label">{{t 'servicePage.certsTab.default'}}:</label>
{{#if model.service.lbConfig.defaultCertificateId}}
<a href="{{href-to "certificates.detail" model.service.lbConfig.defaultCertificateId}}">{{model.service.lbConfig.defaultCertificate.displayName}}</a>
{{else}}
<div class="text-muted">{{t 'generic.none'}}</div>
{{/if}}
</div>
<div class="box col span-6">
<label class="acc-label">{{t 'servicePage.certsTab.additional'}}:</label>
{{#if model.service.lbConfig.certificateIds.length}}
<ul class="list-unstyled">
{{#each model.service.lbConfig.certificates as |cert|}}
<li>
<a href="{{href-to "certificates.detail" cert.id}}">{{cert.displayName}}</a>
</li>
{{/each}}
</ul>
{{else}}
<div class="text-muted">{{t 'generic.none'}}</div>
{{/if}}
</div>
</div>
{{/accordion-list-item}}
{{container/form-command
tagName=''
instance=service
isService=true
initialLabels=service.launchConfig.labels
editing=false
expandAll=al.expandAll
expandFn=expandFn
}}
{{#accordion-list-item
title=(t 'servicePage.containersTab.title')
detail=(t 'servicePage.containersTab.detail')
status=(t 'servicePage.containersTab.status' count=model.service.instances.length)
statusClass=(if model.service.instances.length 'bg-success' 'text-muted')
expandAll=al.expandAll
expand=(action expandFn)
componentName='container-table'
as | parent |
}}
{{component parent.intent
body=model.service.instances
bulkActions=true
showHost=true
}}
{{/accordion-list-item}}
{{labels-section model=model.service.launchConfig tagName='' expandAll=al.expandAll expandFn=expandFn}}
{{#accordion-list-item
title=(t 'servicePage.linksTab.header')
detail=(t 'servicePage.linksTab.detail')
status=(t 'servicePage.linksTab.status' count=model.service.consumedServicesWithNames.length)
statusClass=(if model.service.consumedServicesWithNames.length 'bg-success' 'text-muted')
expandAll=al.expandAll
expand=(action expandFn)
}}
<label class="acc-label">{{t 'servicePage.linksTab.header'}}</label>
<ul class="list-unstyled list-inline with-room">
{{#each model.service.consumedServicesWithNames as |link|}}
<li>{{consumed-service-link link=link stackId=model.service.stackId}}</li>
{{else}}
<li class="text-muted">{{t 'servicePage.linksTab.noData'}}</li>
{{/each}}
</ul>
{{/accordion-list-item}}
{{#accordion-list-item
title=(t 'servicePage.logTab.title')
detail=(t 'servicePage.logTab.detail')
status=(t 'servicePage.logTab.status' count=model.logs.arrangedContent.length)
statusClass=(if model.logs.arrangedContent.length 'bg-success' 'text-muted')
expandAll=al.expandAll
expand=(action expandFn)
}}
<table class="grid fixed">
<thead>
<tr class="fixed-header">
<th width="120">{{t 'servicePage.logTab.table.header.date'}}</th>
<th width="100">{{t 'servicePage.logTab.table.header.level'}}</th>
<th>{{t 'servicePage.logTab.table.header.event'}}</th>
<th>{{t 'servicePage.logTab.table.header.description'}}</th>
<th class="actions" width="75">&nbsp;</th>
</tr>
</thead>
<tbody>
{{#each model.logs.arrangedContent as |obj|}}
<tr class="main-row">
<td>
{{date-str obj.created format="hh:mm:ss A"}}
</td>
<td>
<span class="state badge-sm {{obj.stateColor}} {{obj.stateBackground}}">{{upper-case obj.level}}</span>
</td>
<td>
{{obj.eventType}}{{#if obj.runTime}} ({{obj.runTime}}){{/if}}
</td>
<td>
{{obj.description}}
</td>
<td data-title="{{t 'generic.actions'}}:" class="actions">
{{action-menu model=obj}}
</td>
</tr>
{{else}}
<tr>
<td colspan="5">
<div class="text-muted text-center p-10">{{t 'servicePage.logTab.table.body.noData'}}</div>
</td>
</tr>
{{/each}}
</tbody>
</table>
{{/accordion-list-item}}
</div>
</div>
{{/accordion-list}} {{/accordion-list}}
</section> </section>

View File

@ -49,6 +49,7 @@ module.exports = function(defaults) {
// These get version added to the query string so JS doesn't have to know the fingerprint // These get version added to the query string so JS doesn't have to know the fingerprint
'assets/intl', 'assets/intl',
'assets/images/resources',
'ui-light.css', 'ui-light.rtl.css', 'ui-light.css', 'ui-light.rtl.css',
'ui-dark.css', 'ui-dark.rtl.css', 'ui-dark.css', 'ui-dark.rtl.css',
'ui.css', 'ui.rtl.css', 'ui.css', 'ui.rtl.css',

View File

@ -1119,8 +1119,8 @@ servicePage:
noData: This Service has no ports. noData: This Service has no ports.
notActive: Ports are only available while the service is Active. notActive: Ports are only available while the service is Active.
logTab: logTab:
title: Logs title: Service Log
detail: 'These properties show the log options for this serivce.' detail: 'Recent orchestration events that have occurred for this service'
status: | status: |
{count, plural, {count, plural,
=0 {No events} =0 {No events}
@ -3535,6 +3535,11 @@ pagination:
=0 {No Items} =0 {No Items}
=1 {{count} {count, plural, =1 {Item} other {Items}}} =1 {{count} {count, plural, =1 {Item} other {Items}}}
other {{from} - {to} of {count} Items}} other {{from} - {to} of {count} Items}}
entry: |
{pages, plural,
=0 {No Entries}
=1 {{count} {count, plural, =1 {Entry} other {Entries}}}
other {{from} - {to} of {count} Entries}}
host: | host: |
{pages, plural, {pages, plural,
=0 {No Hosts} =0 {No Hosts}
@ -3656,6 +3661,14 @@ serviceLink:
sameStack: "{service}" sameStack: "{service}"
differentStack: "{stack}/{service}" differentStack: "{stack}/{service}"
serviceLog:
time: Time
level: Level
event: Event
detail: Detai
noMatch: No events match the current search
noData: No events have occurred recently
siteAccess: siteAccess:
header: Site Access header: Site Access
helpText: "Configure who should be allowed to log in and use {appName}." helpText: "Configure who should be allowed to log in and use {appName}."