diff --git a/Pushy/Pushy/Components/App.razor b/Pushy/Pushy/Components/App.razor
index 81c66db..7f4d099 100644
--- a/Pushy/Pushy/Components/App.razor
+++ b/Pushy/Pushy/Components/App.razor
@@ -1,4 +1,9 @@
-
+@using System.Text.Json
+@using Elastic.Apm
+@inject IApmAgent Agent
+@inject IHostEnvironment Environment
+
+
@@ -13,6 +18,21 @@
+ @if (Agent.Configuration.Enabled)
+ {
+
+
+ }
\ No newline at end of file
diff --git a/Pushy/Pushy/Components/Pages/Home.razor b/Pushy/Pushy/Components/Pages/Home.razor
index 7c2632f..6f2a346 100644
--- a/Pushy/Pushy/Components/Pages/Home.razor
+++ b/Pushy/Pushy/Components/Pages/Home.razor
@@ -42,6 +42,7 @@
CreatedItems.Add(item);
Form = new UploadForm();
+ Logger.LogInformation("A new item was created!");
}
public sealed class UploadForm
diff --git a/Pushy/Pushy/Grains/TextItemGrain.cs b/Pushy/Pushy/Grains/TextItemGrain.cs
index 1469289..780c2ac 100644
--- a/Pushy/Pushy/Grains/TextItemGrain.cs
+++ b/Pushy/Pushy/Grains/TextItemGrain.cs
@@ -25,6 +25,7 @@ public interface ITextItem : IGrainWithStringKey
public sealed class TextItemGrain : Grain, ITextItem, IRemindable
{
private readonly IPersistentState _state;
+
private IGrainReminder? _reminder;
public TextItemGrain(
diff --git a/Pushy/Pushy/Program.cs b/Pushy/Pushy/Program.cs
index 0a021e1..b1c78b5 100644
--- a/Pushy/Pushy/Program.cs
+++ b/Pushy/Pushy/Program.cs
@@ -1,3 +1,6 @@
+using Elastic.Extensions.Logging;
+using Elastic.Extensions.Logging.Options;
+using Elastic.Transport;
using Pushy.Components;
using StackExchange.Redis;
using LinkGenerator = Pushy.LinkGenerator;
@@ -9,21 +12,43 @@ builder.UseOrleans(silo =>
silo.UseLocalhostClustering();
silo.UseRedisReminderService(conf =>
{
- conf.ConfigurationOptions = ConfigurationOptions.Parse(builder.Configuration.GetConnectionString("Valkey"));
+ conf.ConfigurationOptions = ConfigurationOptions.Parse(builder.Configuration.GetConnectionString("Valkey")!);
});
silo.AddRedisGrainStorageAsDefault(options =>
{
options.ConfigurationOptions =
- ConfigurationOptions.Parse(builder.Configuration.GetConnectionString("Valkey"));
+ ConfigurationOptions.Parse(builder.Configuration.GetConnectionString("Valkey")!);
});
silo.AddActivityPropagation();
});
+var transport = new TransportConfiguration(new StaticNodePool([new Uri("https://elastic-node-1.home.local:9200")]))
+ .Authentication(new ApiKey(builder.Configuration["Elasticsearch:ApiKey"]!));
+
+builder.Logging.AddElasticsearch(opt =>
+{
+ opt.IsEnabled = true;
+ opt.DataStream = new DataStreamNameOptions()
+ {
+ Type = "logs", DataSet = "Pushy", Namespace = "pushy"
+ };
+ opt.Transport = new DistributedTransport(transport);
+});
+
builder.Services.AddScoped();
+builder.Services.AddAllElasticApm();
builder.Services.AddHealthChecks();
+builder.Services.AddCors(policy =>
+{
+ policy.AddDefaultPolicy(builder =>
+ {
+ builder.WithOrigins("https://henrikml.dk")
+ .AllowAnyHeader();
+ });
+});
// Add services to the container.
builder.Services.AddRazorComponents()
@@ -35,6 +60,7 @@ builder.Services.AddResponseCompression();
var app = builder.Build();
+
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
@@ -51,6 +77,7 @@ else
app.UseHttpsRedirection();
app.UseResponseCompression();
+app.UseCors();
app.MapStaticAssets();
app.UseAntiforgery();
diff --git a/Pushy/Pushy/Pushy.csproj b/Pushy/Pushy/Pushy.csproj
index eb75f8e..17bba3d 100644
--- a/Pushy/Pushy/Pushy.csproj
+++ b/Pushy/Pushy/Pushy.csproj
@@ -10,6 +10,8 @@
+
+
diff --git a/Pushy/Pushy/appsettings.json b/Pushy/Pushy/appsettings.json
index 10f68b8..4359f0c 100644
--- a/Pushy/Pushy/appsettings.json
+++ b/Pushy/Pushy/appsettings.json
@@ -2,8 +2,14 @@
"Logging": {
"LogLevel": {
"Default": "Information",
- "Microsoft.AspNetCore": "Warning"
+ "Microsoft.AspNetCore": "Warning",
+ "Elastic.Apm": "Warning"
}
},
- "AllowedHosts": "*"
+ "AllowedHosts": "*",
+ "ElasticApm":
+ {
+ "ServerUrl": "http://apm.home.local:8200",
+ "TransactionNameGroups": "GET /t/*"
+ }
}
diff --git a/Pushy/Pushy/wwwroot/elastic-apm-rum.umd.min.js b/Pushy/Pushy/wwwroot/elastic-apm-rum.umd.min.js
new file mode 100644
index 0000000..4a3542f
--- /dev/null
+++ b/Pushy/Pushy/wwwroot/elastic-apm-rum.umd.min.js
@@ -0,0 +1,2 @@
+!function(){var t={816:function(t,e,n){var r,i,a;!function(o,s){"use strict";i=[n(170)],void 0===(a="function"==typeof(r=function(t){var e=/(^|@)\S+\:\d+/,n=/^\s*at .*(\S+\:\d+|\(native\))/m,r=/^(eval@)?(\[native code\])?$/;function i(t,e,n){if("function"==typeof Array.prototype.map)return t.map(e,n);for(var r=new Array(t.length),i=0;i-1&&(e=e.replace(/eval code/g,"eval").replace(/(\(eval at [^\()]*)|(\)\,.*$)/g,""));var n=e.replace(/^\s+/,"").replace(/\(eval code/g,"(").split(/\s+/).slice(1),r=this.extractLocation(n.pop()),i=n.join(" ")||void 0,a=function(t,e){if("function"==typeof Array.prototype.indexOf)return t.indexOf(e);for(var n=0;n"],r[0])>-1?void 0:r[0];return new t(i,void 0,a,r[1],r[2],e)}),this)},parseFFOrSafari:function(e){return i(a(e.stack.split("\n"),(function(t){return!t.match(r)}),this),(function(e){if(e.indexOf(" > eval")>-1&&(e=e.replace(/ line (\d+)(?: > eval line \d+)* > eval\:\d+\:\d+/g,":$1")),-1===e.indexOf("@")&&-1===e.indexOf(":"))return new t(e);var n=e.split("@"),r=this.extractLocation(n.pop()),i=n.join("@")||void 0;return new t(i,void 0,r[0],r[1],r[2],e)}),this)},parseOpera:function(t){return!t.stacktrace||t.message.indexOf("\n")>-1&&t.message.split("\n").length>t.stacktrace.split("\n").length?this.parseOpera9(t):t.stack?this.parseOpera11(t):this.parseOpera10(t)},parseOpera9:function(e){for(var n=/Line (\d+).*script (?:in )?(\S+)/i,r=e.message.split("\n"),i=[],a=2,o=r.length;a/,"$2").replace(/\([^\)]*\)/g,"")||void 0;a.match(/\(([^\)]*)\)/)&&(n=a.replace(/^[^\(]+\(([^\)]*)\)$/,"$1"));var s=void 0===n||"[arguments not available]"===n?void 0:n.split(",");return new t(o,s,i[0],i[1],i[2],e)}),this)}}})?r.apply(e,i):r)||(t.exports=a)}()},170:function(t,e){var n,r,i;!function(a,o){"use strict";r=[],void 0===(i="function"==typeof(n=function(){function t(t){return!isNaN(parseFloat(t))&&isFinite(t)}function e(t,e,n,r,i,a){void 0!==t&&this.setFunctionName(t),void 0!==e&&this.setArgs(e),void 0!==n&&this.setFileName(n),void 0!==r&&this.setLineNumber(r),void 0!==i&&this.setColumnNumber(i),void 0!==a&&this.setSource(a)}return e.prototype={getFunctionName:function(){return this.functionName},setFunctionName:function(t){this.functionName=String(t)},getArgs:function(){return this.args},setArgs:function(t){if("[object Array]"!==Object.prototype.toString.call(t))throw new TypeError("Args must be an Array");this.args=t},getFileName:function(){return this.fileName},setFileName:function(t){this.fileName=String(t)},getLineNumber:function(){return this.lineNumber},setLineNumber:function(e){if(!t(e))throw new TypeError("Line Number must be a Number");this.lineNumber=Number(e)},getColumnNumber:function(){return this.columnNumber},setColumnNumber:function(e){if(!t(e))throw new TypeError("Column Number must be a Number");this.columnNumber=Number(e)},getSource:function(){return this.source},setSource:function(t){this.source=String(t)},toString:function(){return(this.getFunctionName()||"{anonymous}")+("("+(this.getArgs()||[]).join(",")+")")+(this.getFileName()?"@"+this.getFileName():"")+(t(this.getLineNumber())?":"+this.getLineNumber():"")+(t(this.getColumnNumber())?":"+this.getColumnNumber():"")}},e})?n.apply(e,r):n)||(t.exports=i)}()}},e={};function n(r){var i=e[r];if(void 0!==i)return i.exports;var a=e[r]={exports:{}};return t[r].call(a.exports,a,a.exports,n),a.exports}n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,{a:e}),e},n.d=function(t,e){for(var r in e)n.o(e,r)&&!n.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},function(){"use strict";var t=function(t){var e=this.constructor;return this.then((function(n){return e.resolve(t()).then((function(){return n}))}),(function(n){return e.resolve(t()).then((function(){return e.reject(n)}))}))},e=setTimeout;function r(t){return Boolean(t&&void 0!==t.length)}function i(){}function a(t){if(!(this instanceof a))throw new TypeError("Promises must be constructed via new");if("function"!=typeof t)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=void 0,this._deferreds=[],d(t,this)}function o(t,e){for(;3===t._state;)t=t._value;0!==t._state?(t._handled=!0,a._immediateFn((function(){var n=1===t._state?e.onFulfilled:e.onRejected;if(null!==n){var r;try{r=n(t._value)}catch(t){return void c(e.promise,t)}s(e.promise,r)}else(1===t._state?s:c)(e.promise,t._value)}))):t._deferreds.push(e)}function s(t,e){try{if(e===t)throw new TypeError("A promise cannot be resolved with itself.");if(e&&("object"==typeof e||"function"==typeof e)){var n=e.then;if(e instanceof a)return t._state=3,t._value=e,void u(t);if("function"==typeof n)return void d((r=n,i=e,function(){r.apply(i,arguments)}),t)}t._state=1,t._value=e,u(t)}catch(e){c(t,e)}var r,i}function c(t,e){t._state=2,t._value=e,u(t)}function u(t){2===t._state&&0===t._deferreds.length&&a._immediateFn((function(){t._handled||a._unhandledRejectionFn(t._value)}));for(var e=0,n=t._deferreds.length;e0)return r}}()}}function O(t){return C(t,h.call(arguments,1),!1)}function N(t){return C(t,h.call(arguments,1),!0)}function j(t){return void 0===t}function R(){}function q(t){return t.replace(/[.*"]/g,"_")}function F(t,e){for(var n=null,r=0;r=0?t:A()}function M(t,e){return j(e)||j(t)?null:parseInt(e-t)}function H(t){v.resolve().then(t)}function U(){return"function"==typeof m.getEntriesByType}function z(t){return"undefined"!=typeof PerformanceObserver&&PerformanceObserver.supportedEntryTypes&&PerformanceObserver.supportedEntryTypes.indexOf(t)>=0}function D(){return"interactionCount"in performance}function B(t){return t.redirectStart>0}var V={fetchInProgress:!1};function $(t){return"__apm_symbol__"+t}function J(t,e,n){for(var r=t;r&&!r.hasOwnProperty(e);)r=Object.getPrototypeOf(r);!r&&t[e]&&(r=t);var i,a,o,s,c=$(e);if(r&&!(i=r[c])){i=r[c]=r[e];var u=r&&Object.getOwnPropertyDescriptor(r,e);if(!(s=u)||!1!==s.writable&&("function"!=typeof s.get||void 0!==s.set)){var f=n(i,c,e);r[e]=function(){return f(this,arguments)},a=r[e],o=i,a[$("OriginalDelegate")]=o}}return i}var X=$("xhrIgnore"),G=$("xhrSync"),Z=$("xhrURL"),Y=$("xhrMethod"),Q="invoke",W=["link","css","script","img","xmlhttprequest","fetch","beacon","iframe"],K="page-load",tt=[K,"route-change","user-interaction","http-request","custom","temporary"];function et(t){var e=XMLHttpRequest.prototype;if(e&&e.addEventListener)var n=J(e,"open",(function(){return function(t,e){return t[X]||(t[Y]=e[0],t[Z]=e[1],t[G]=!1===e[2]),n.apply(t,e)}})),r=J(e,"send",(function(){return function(e,n){if(e[X])return r.apply(e,n);var a={source:"xmlhttprequest",state:"",type:"macroTask",data:{target:e,method:e[Y],sync:e[G],url:e[Z],status:""}};try{return function(e){if("schedule"!==e.state){e.state="schedule",t("schedule",e);var n=e.data.target;r("readystatechange"),r("load"),r("timeout"),r("error"),r("abort")}function r(t){n.addEventListener(t,(function(t){var r=t.type;"readystatechange"===r?4===n.readyState&&0!==n.status&&i(e,"success"):i(e,"load"===r?"success":r)}))}}(a),r.apply(e,n)}catch(t){throw i(a,"error"),t}}}));function i(e,n){e.state!==Q&&(e.state=Q,e.data.status=n,t(Q,e))}}function nt(t){return!(0===t||t>399&&t<600)}function rt(){return(rt=Object.assign||function(t){for(var e=1;e-1&&n.observers[t].splice(r,1)}},e.sendOnly=function(t,e){var n=this.observers[t];n&&n.forEach((function(t){try{t.apply(void 0,e)}catch(t){console.log(t,t.stack)}}))},e.send=function(t,e){this.sendOnly(t+":before",e),this.sendOnly(t,e),this.sendOnly(t+":after",e)},t}(),st=new ot,ct=!1;function ut(){return ct||(ct=!0,et((function(t,e){st.send("xmlhttprequest",[t,e])})),function(t){if(at()){var e=window.fetch;window.fetch=function(t,o){var s,c,u=this,f=arguments,d=t instanceof URL;if("string"==typeof t||d)s=new Request(t,o),c=d?s.url:t;else{if(!t)return e.apply(u,f);c=(s=t).url}var l={source:"fetch",state:"",type:"macroTask",data:{target:s,method:s.method,url:c,aborted:!1}};return new v((function(t,o){var c;V.fetchInProgress=!0,n(l);try{c=e.apply(u,[s])}catch(t){return o(t),l.data.error=t,r(l),void(V.fetchInProgress=!1)}c.then((function(e){var n=e.clone?e.clone():{};t(e),H((function(){l.data.response=e;var t=n.body;t?a(t,l):r(l)}))}),(function(t){o(t),H((function(){i(l,t)}))})),V.fetchInProgress=!1}))}}function n(e){e.state="schedule",t("schedule",e)}function r(e){e.state=Q,t(Q,e)}function i(t,e){t.data.aborted=function(t){return t&&"AbortError"===t.name}(e),t.data.error=e,r(t)}function a(t,e){var n=t.getReader();!function t(){n.read().then((function(n){n.done?r(e):t()}),(function(t){i(e,t)}))}()}}((function(t,e){st.send("fetch",[t,e])})),function(t){if(window.history){var e=history.pushState;"function"==typeof e&&(history.pushState=function(n,r,i){var a={source:"history",data:{state:n,title:r,url:i}};t(Q,a),e.apply(this,arguments)})}}((function(t,e){st.send("history",[t,e])}))),st}var ft={bootstrapTime:null,lastHiddenStart:Number.MIN_SAFE_INTEGER},dt=!1;function lt(){return E()?(ut(),ft.bootstrapTime=A(),dt=!0):g&&console.log("[Elastic APM] platform is not supported!"),dt}function pt(t,e){var n=e.error,r=e.filename,i=e.lineno,a=e.colno,o=[];if(n)try{o=t.parse(n)}catch(t){}return function(t){return 0!==t.length&&(1!==t.length||"lineNumber"in t[0])}(o)||(o=[{fileName:r,lineNumber:i,columnNumber:a}]),o.map((function(t){return t.functionName&&(t.functionName=(e=t.functionName,n=e.split("/"),e=(e=(e=n.length>1?["Object",n[n.length-1]].join("."):n[0]).replace(/.<$/gi,".")).replace(/^Anonymous function$/,""),e=(n=e.split(".")).length>1?n[n.length-1]:n[0])),t;var e,n})).map((function(t){var e=t.fileName,n=t.lineNumber,r=t.columnNumber,i=t.functionName,a=void 0===i?"":i;if(!e&&!n)return{};if(!r&&!n)return{};var o,s,c=function(t){return void 0===t&&(t=""),""===t&&(t=""),t}(e),u=(o=c,s=window.location.origin||window.location.protocol+"//"+window.location.hostname+(window.location.port?":"+window.location.port:""),o.indexOf(s)>-1&&(o=o.replace(s+"/","")),o);return function(t){return!!t&&0===window.location.href.indexOf(t)}(c)&&(u="(inline script)"),{abs_path:e,filename:u,function:a,lineno:n,colno:r}}))}var vt=[["#","hash"],["?","query"],["/","path"],["@","auth",1],[NaN,"host",void 0,1]],ht=/^([a-z][a-z0-9.+-]*:)?(\/\/)?([\S\s]*)/i,gt=function(){function t(t){var e,n=this.extractProtocol(t||""),r=n.protocol,i=n.address,a=n.slashes,o=!r&&!a,s=this.getLocation(),c=vt.slice();i=i.replace("\\","/"),a||(c[2]=[NaN,"path"]);for(var u=0;u=0||(i[n]=t[n]);return i}(n,mt)),i=_t(),a={};if("page-exit"===t.type)t.ensureContext(),t.context.page&&t.context.page.url&&(i.page.url=t.context.page.url);else if(t.type===K&&U()){var o=m.getEntriesByType("navigation");o&&o.length>0&&(a={response:yt(o[0])})}t.addContext(i,a,r)}var Tt={service:{name:[1024,!0],version:!0,agent:{version:[1024,!0]},environment:!0},labels:{"*":!0}},Et={"*":!0,headers:{"*":!0}},xt={user:{id:!0,email:!0,username:!0},tags:{"*":!0},http:{response:Et},destination:{address:[1024],service:{"*":[1024,!0]}},response:Et},kt={name:[1024,!0],type:[1024,!0],id:[1024,!0],trace_id:[1024,!0],parent_id:[1024,!0],transaction_id:[1024,!0],subtype:!0,action:!0,context:xt},It={name:!0,parent_id:!0,type:[1024,!0],id:[1024,!0],trace_id:[1024,!0],span_count:{started:[1024,!0]},context:xt},Ct={id:[1024,!0],trace_id:!0,transaction_id:!0,parent_id:!0,culprit:!0,exception:{type:!0},transaction:{type:!0},context:xt};function Lt(t){return null==t||""===t||void 0===t}function Ot(t,e,n){var r=function(t,e,n,r){return void 0===e&&(e=1024),void 0===n&&(n=!1),void 0===r&&(r="N/A"),n&&Lt(t)&&(t=r),"string"==typeof t?t.substring(0,e):t}(t[e],n[0],n[1]);Lt(r)?delete t[e]:t[e]=r}function Nt(t,e,n){void 0===t&&(t={}),void 0===n&&(n=e);for(var r=Object.keys(t),i=[],a=function(a){var o=r[a],s=!0===t[o]?i:t[o];Array.isArray(s)?"*"===o?Object.keys(n).forEach((function(t){return Ot(n,t,s)})):Ot(n,o,s):Nt(s,e,n[o])},o=0;o=0)){var i=t[r];if(null!=i&&"function"!=typeof i){if("object"==typeof i){if("function"!=typeof i.toISOString)return;i=i.toISOString()}n[r]=i,e=!0}}})),e)return n}(a);u&&(c.custom=u)}s||o&&o.indexOf(":")>-1&&(s=o.split(":")[0]);var f=this._transactionService.getCurrentTransaction(),d=f?f.context:{},l=this._configService.get("context"),p=(l.tags,function(t,e){if(null==t)return{};var n,r,i={},a=Object.keys(t);for(r=0;r=0||(i[n]=t[n]);return i}(l,qt)),v=N({},_t(),d,p,c),h={id:b(),culprit:n,exception:{message:o,stacktrace:e,type:s},context:v};return f&&(h=O(h,{trace_id:f.traceId,parent_id:f.id,transaction_id:f.id,transaction:{type:f.type,sampled:f.sampled}})),Nt(Ct,h)},e.logErrorEvent=function(t){if(void 0!==t){var e=this.createErrorDataModel(t);void 0!==e.exception.message&&this._apmServer.addError(e)}},e.registerListeners=function(){var t=this;window.addEventListener("error",(function(e){return t.logErrorEvent(e)})),window.addEventListener("unhandledrejection",(function(e){return t.logPromiseEvent(e)}))},e.logPromiseEvent=function(t){var e,n=t.reason;(null==n&&(n=""),"string"==typeof n.message)?e={error:n,message:"Unhandled promise rejection: "+(n.name?n.name+": ":"")+n.message}:e=this._parseRejectReason(n);this.logErrorEvent(e)},e.logError=function(t){var e={};return"string"==typeof t?e.message=t:e.error=t,this.logErrorEvent(e)},e._parseRejectReason=function(t){var e={message:"Unhandled promise rejection: "};if(Array.isArray(t))e.message+="