Skip to content

Commit 147ddda

Browse files
committed
Add Analytics + Logging to AI Server's Admin UI
1 parent f1a23ff commit 147ddda

15 files changed

+4150
-145
lines changed

AiServer/AiServer.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,9 @@
3333
<ItemGroup>
3434
<Folder Include="wwwroot\img\langs\" />
3535
</ItemGroup>
36+
37+
<ItemGroup>
38+
<_ContentIncludedByDefault Remove="wwwroot\modules\admin-ui\components\Analytics2.mjs" />
39+
</ItemGroup>
3640

3741
</Project>

AiServer/Configure.AppHost.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using AiServer.ServiceInterface;
33
using AiServer.ServiceInterface.Generation;
44
using AiServer.ServiceModel;
5+
using ServiceStack.Admin;
56
using ServiceStack.Configuration;
67
using ServiceStack.Data;
78
using ServiceStack.IO;
@@ -175,7 +176,18 @@ public override void Configure()
175176
typeof(AdminJobDashboard),
176177
typeof(AdminRequeueFailedJobs),
177178
typeof(AdminGetJobProgress),
178-
typeof(QueryPrompts),
179+
typeof(QueryPrompts),
180+
181+
typeof(Authenticate),typeof(AuthenticateResponse),
182+
typeof(GetAccessToken),typeof(GetAccessTokenResponse),
183+
typeof(AdminDatabase),typeof(AdminDatabaseResponse),
184+
typeof(AdminCreateUser),typeof(AdminDeleteUser),typeof(AdminDeleteUserResponse),typeof(AdminGetUser),typeof(AdminUserResponse),
185+
typeof(AdminQueryUsers),typeof(AdminUpdateUser),typeof(AdminUserBase),typeof(AdminUsersResponse),
186+
typeof(AdminGetRoles),typeof(AdminGetRolesResponse),typeof(AdminGetRole),typeof(AdminGetRoleResponse),
187+
typeof(AdminCreateRole),typeof(AdminUpdateRole),typeof(AdminDeleteRole),
188+
typeof(RequestLogs),typeof(RequestLogsResponse),
189+
typeof(GetValidationRules),typeof(ModifyValidationRules),typeof(ValidationRule),typeof(ValidateRule),
190+
typeof(GetValidationRulesResponse),
179191
];
180192

181193
// Avoid having to re-renter AuthSecret and API Keys during Development

AiServer/wwwroot/admin/index.html

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@
2020
"marked": "/lib/mjs/marked.mjs",
2121
"highlight.mjs": "/lib/mjs/highlight.mjs",
2222
"chart.js": "/lib/mjs/chart.js",
23+
"charts": "/lib/mjs/charts.mjs",
2324
"color.js": "/lib/mjs/color.js",
2425
"dtos": "/mjs/dtos.mjs",
25-
"core": "/js/core.mjs"
26+
"core": "/js/core.mjs",
27+
"app": "/lib/mjs/app.mjs"
2628
}
2729
}
2830
</script>
@@ -147,6 +149,9 @@ <h1 v-if="activeSection.title" class="hidden lg:block pt-4 mb-2 text-3xl font-bo
147149
import CopyIcon from "/js/components/CopyIcon.mjs"
148150
import SortableColumn from "/js/components/SortableColumn.mjs"
149151
import { BackgroundJobs } from "/modules/admin-ui/components/BackgroundJobs.mjs"
152+
import { Analytics } from "/modules/admin-ui/components/Analytics.mjs"
153+
import { Logging } from "/modules/admin-ui/components/Logging.mjs"
154+
import { LogLinks } from "/modules/admin-ui/components/LogLinks.mjs"
150155
import { ApiKeys } from "/modules/admin-ui/components/ApiKeys.mjs"
151156
import { CreateApiKeyForm, EditApiKeyForm } from "/modules/admin-ui/components/ManageUserApiKeys.mjs"
152157
import { ApiKeyDialog } from "/js/components/ApiKeyDialog.mjs"
@@ -170,12 +175,14 @@ <h1 v-if="activeSection.title" class="hidden lg:block pt-4 mb-2 text-3xl font-bo
170175
const app = new App()
171176
app.use(ServiceStackVue)
172177
app.component('RouterLink', ServiceStackVue.component('RouterLink'))
173-
app.components({ CreateApiKeyForm, EditApiKeyForm, ApiKeyDialog, CopyIcon, SortableColumn, SignInForm })
178+
app.components({ CreateApiKeyForm, EditApiKeyForm, ApiKeyDialog, CopyIcon, SortableColumn, SignInForm, LogLinks })
174179

175180
let routes = usePageRoutes(app, {
176181
page:'admin',
177-
queryKeys: ('tab,provider,db,schema,table,q,page,sort,new,edit,op,skip,id,' +
178-
'show,orderBy,pathInfo,tag,body,type,dialog,period').split(','),
182+
queryKeys: ('id,' +
183+
'tab,provider,db,schema,table,q,page,sort,new,edit,op,skip,' +
184+
'show,orderBy,operationName,userAuthId,sessionId,pathInfo,ipAddress,referer,forwardedFor,hasResponse,withErrors,' +
185+
'source,threadId,eventType,traceId,userId,tag,body,type,dialog,period,year,month,ip,apiKey,apiKeyId').split(','),
179186
handlers: {
180187
init(state) { console.debug('init', state) }, /*debug*/
181188
nav(state) { console.debug('nav', state) } /*debug*/
@@ -373,17 +380,30 @@ <h4 class="mt-4 font-semibold text-gray-500">By Month</h4>
373380
template:`<AutoQueryGrid :type="type" />`,
374381
},
375382
},
376-
BackgroundJobs: {
383+
384+
analytics: {
385+
group: 'ADMIN',
386+
type: 'Analytics',
387+
component: Analytics,
388+
icon: iconDataUri('<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true"><path fill="currentColor" d="M13 5h2v14h-2zm-2 4H9v10h2zm-4 4H5v6h2zm12 0h-2v6h2z"></path></svg>'),
389+
},
390+
backgroundjobs: {
377391
group: 'ADMIN',
378392
type: 'BackgroundJob',
379393
component: BackgroundJobs,
380394
icon: icons.queue,
381395
},
382-
ApiKeys: {
396+
apikeys: {
383397
group: 'ADMIN',
384398
component: ApiKeys,
385399
icon: iconDataUri('<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true"><path fill="currentColor" d="M10.32 2.013A4 4 0 0 0 6.162 7.13l-3.987 3.986a.6.6 0 0 0-.176.424v2.86a.6.6 0 0 0 .6.6h2.8a.6.6 0 0 0 .6-.6V13h1.9a.6.6 0 0 0 .6-.6v-1.693l.735-.735a5.5 5.5 0 0 1-.569-.846l-.99.991a.6.6 0 0 0-.176.424V12H5.6a.6.6 0 0 0-.6.6V14H3v-2.293l4.32-4.32l-.118-.303a3 3 0 0 1 1.96-3.965c.33-.423.72-.796 1.157-1.106M13.5 6.25a.75.75 0 1 0 0-1.5a.75.75 0 0 0 0 1.5M9 6.5a4.5 4.5 0 1 1 7 3.742v2.05l.783.784a.6.6 0 0 1 0 .848L15.707 15l1.068 1.067a.6.6 0 0 1-.05.893l-2.35 1.88a.6.6 0 0 1-.75 0l-2.4-1.92a.6.6 0 0 1-.225-.468v-6.21A4.5 4.5 0 0 1 9 6.5M13.5 3a3.5 3.5 0 0 0-1.75 6.532a.5.5 0 0 1 .25.433v6.295l2 1.6l1.751-1.401l-1.034-1.035a.6.6 0 0 1 0-.848l1.076-1.076l-.617-.617a.6.6 0 0 1-.176-.424V9.965a.5.5 0 0 1 .25-.433A3.5 3.5 0 0 0 13.5 3"></path></svg>'),
386400
},
401+
logging: {
402+
group: 'ADMIN',
403+
type: 'Logging',
404+
component: Logging,
405+
icon: iconDataUri('<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13V5a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v13c0 1-.6 3-3 3m0 0H6c-1 0-3-.6-3-3v-2h12v2c0 2.4 2 3 3 3zM9 7h8m-8 4h4"></path></svg>'),
406+
},
387407
}
388408
function getIcon(id) {
389409
const section = sections[id]
@@ -409,7 +429,7 @@ <h4 class="mt-4 font-semibold text-gray-500">By Month</h4>
409429
const showUserMenu = ref(false)
410430
const init = ref(false)
411431
const apiKeyError = ref('')
412-
console.log('AppComponent', routes.admin)
432+
//console.log('AppComponent', routes.admin)
413433
const activeSection = shallowRef(sections[routes.admin] || sections.Dashboard)
414434

415435
function navTo(section, args, pushState=true) {
@@ -472,7 +492,15 @@ <h4 class="mt-4 font-semibold text-gray-500">By Month</h4>
472492

473493
const client = window.client = new JsonServiceClient()
474494
const events = app.events
475-
app.provides({ client, routes, server, store, events, })
495+
app.provides({ app, client, routes, server, store, events, })
496+
497+
app.directive('highlightjs', (el, binding) => {
498+
if (binding.value) {
499+
//el.className = ''
500+
el.innerHTML = enc(binding.value)
501+
globalThis.hljs.highlightElement(el)
502+
}
503+
})
476504

477505
app.build(AppComponent).mount('#app')
478506
app.start()

0 commit comments

Comments
 (0)