Я предполагаю, что вы должны создать службу анализа приложений, как показано ниже:
import {Injectable} from '@angular/core';
import {AppInsights} from 'applicationinsights-js';
@Injectable()
export class MonitoringService {
private config: Microsoft.ApplicationInsights.IConfig = {
instrumentationKey: 'KEY_GOES_HERE',
enableDebug: true,
verboseLogging: true
};
constructor() {
if (!AppInsights.config) {
AppInsights.downloadAndSetup(this.config);
}
}
logPageView(name?: string, url?: string, properties?: any, measurements?: any, duration?: number) {
AppInsights.trackPageView(name, url, properties, measurements, duration);
}
logEvent(name: string, properties?: any, measurements?: any) {
AppInsights.trackEvent(name, properties, measurements);
}
trackException(exception: Error) {
AppInsights.trackException(exception);
}
}
Angular обрабатывает все необработанные исключения, поэтому он также должен хранить все 404. Попробуйте реализовать https://angular.io/api/core/ErrorHandler и вызовите trackException оттуда.
Это будет пользовательский обработчик ошибок, из которого вы можете отфильтровать URL-адрес, который вы хотите сохранить, а также проверить код ответа 404. Если это так, нет необходимости его сохранять, просто вызовите метод отслеживания исключений. [ 115]
Вот одна хорошая статья для настройки ИИ в угловых SPA.
http://www.andrewconnell.com/blog/using-azure-application-insights-with-single-page-apps
Надеюсь, это поможет.
Вы могли сделать это с Таймером, но у Вас должна будет быть некоторая форма соединения Вашего сканирования базы данных и обновления. Простое lock
синхронизироваться может быть достаточно, чтобы препятствовать тому, чтобы произошли несколько выполнений.
Однако могло бы быть лучше запустить таймер ПОСЛЕ ТОГО, КАК Вы - операция, завершено, и просто используйте его одно время, затем остановите его. Перезапустите его после своей следующей операции. Это дало бы Вам 30 секунд (или секунды N) между событиями без шанса перекрытий и никакой блокировки.
Пример:
System.Threading.Timer timer = null;
timer = new System.Threading.Timer((g) =>
{
Console.WriteLine(1); //do whatever
timer.Change(5000, Timeout.Infinite);
}, null, 0, Timeout.Infinite);
Работайте сразу..... Конец... ожидает 5 секунд.... Работайте сразу..... Конец... ожидает 5 секунд....
Я использовал бы Монитор. TryEnter в Вашем прошедшем коде:
if (Monitor.TryEnter(lockobj))
{
try
{
// we got the lock, do your work
}
finally
{
Monitor.Exit(lockobj);
}
}
else
{
// another elapsed has the lock
}
Я предпочитаю System.Threading.Timer
для вещей как это, потому что я не должен проходить механизм обработки событий:
Timer UpdateTimer = new Timer(UpdateCallback, null, 30000, 30000);
object updateLock = new object();
void UpdateCallback(object state)
{
if (Monitor.TryEnter(updateLock))
{
try
{
// do stuff here
}
finally
{
Monitor.Exit(updateLock);
}
}
else
{
// previous timer tick took too long.
// so do nothing this time through.
}
}
Можно избавить от необходимости блокировку путем создания таймера одноразовым и перезапуска его после каждого обновления:
// Initialize timer as a one-shot
Timer UpdateTimer = new Timer(UpdateCallback, null, 30000, Timeout.Infinite);
void UpdateCallback(object state)
{
// do stuff here
// re-enable the timer
UpdateTimer.Change(30000, Timeout.Infinite);
}
вместо того, чтобы блокировать (который мог заставить все Ваши синхронизированные сканирования ожидать и в конечном счете складывать). Вы могли запустить сканирование/обновление в потоке и затем просто сделать проверку, чтобы видеть, жив ли поток все еще.
Thread updateDBThread = new Thread(MyUpdateMethod);
...
private void timer_Elapsed(object sender, ElapsedEventArgs e)
{
if(!updateDBThread.IsAlive)
updateDBThread.Start();
}
Вы могли использовать AutoResetEvent следующим образом:
// Somewhere else in the code
using System;
using System.Threading;
// In the class or whever appropriate
static AutoResetEvent autoEvent = new AutoResetEvent(false);
void MyWorkerThread()
{
while(1)
{
// Wait for work method to signal.
if(autoEvent.WaitOne(30000, false))
{
// Signalled time to quit
return;
}
else
{
// grab a lock
// do the work
// Whatever...
}
}
}
Немного "более умное" решение находится следующим образом в псевдокоде:
using System;
using System.Diagnostics;
using System.Threading;
// In the class or whever appropriate
static AutoResetEvent autoEvent = new AutoResetEvent(false);
void MyWorkerThread()
{
Stopwatch stopWatch = new Stopwatch();
TimeSpan Second30 = new TimeSpan(0,0,30);
TimeSpan SecondsZero = new TimeSpan(0);
TimeSpan waitTime = Second30 - SecondsZero;
TimeSpan interval;
while(1)
{
// Wait for work method to signal.
if(autoEvent.WaitOne(waitTime, false))
{
// Signalled time to quit
return;
}
else
{
stopWatch.Start();
// grab a lock
// do the work
// Whatever...
stopwatch.stop();
interval = stopwatch.Elapsed;
if (interval < Seconds30)
{
waitTime = Seconds30 - interval;
}
else
{
waitTime = SecondsZero;
}
}
}
}
Любой из них имеет преимущество, что можно завершить работу потока, только путем передачи сигналов о событии.
Править
Я должен добавить, что этот код делает предположение, что у Вас только есть один из этих MyWorkerThreads () выполнение, иначе они работали бы одновременно.