Build version information in Application Insights telemetry (client-side) - javascript

We have a SPA hosted on ASP.NET application. We want to track the build version of the whole app.
So this telemetry initializer
public class VersionInfoTelemetryInitializer : ITelemetryInitializer
{
public void Initialize(ITelemetry telemetry)
{
telemetry.Context.Component.Version =
typeof(Startup).Assembly.GetName().Version.ToString();
}
}
will be used in Gloabal.asax
public class MvcApplication : HttpApplication
{
protected void Application_Start()
{
var tc = TelemetryConfiguration.Active;
tc.InstrumentationKey = ConfigurationManager.AppSettings["AI Instrumentation Key"];
tc.TelemetryInitializers.Add(new VersionInfoTelemetryInitializer());
...
}
}
Server-side telemetry will have version information appended. But I am not able to do the same for the client-side telemetry. I have tried this
var appInsights = window.appInsights || function(config) {
// standard js snippet from azure portal
}({
instrumentationKey: '{{INSTRUMENTATIONKEY}}'
});
window.appInsights = appInsights;
window.appInsights.context.application.ver = 'some version number';
which results in following JS error
Uncaught TypeError: Cannot read property 'application' of undefined
I also tried
appInsights.queue.push(function () {
appInsights.context.addTelemetryInitializer(versionInfoTelemetryInitialier);
});
function versionInfoTelemetryInitialier(envelope) {
var telemetryItem = envelope.data.baseData;
telemetry.context.component.version = 'some version number';
}
which will warn with following message
AI: TelemetryInitializerFailed message:"One of telemetry initializers failed, telemetry
item will not be sent: TypeError" props:"{exception:[object Error]{ stack: 'TypeError:
Unable to get property 'component' of undefined or null reference\n at
versionInfoTelemetryInitialier (https://localhost:44301/landing/index:107:9)\n at
n.prototype._track (https://az416426.vo.msecnd.net/scripts/a/ai.0.js:1:65589)\n at
n.prototype.track...
What should I do so that client-side telemetry has version information attached.

i think your second attempt is very close. you need to do it via the queue, to make sure it occurs after all the AI scripts are actually loaded, so i think this is correct:
appInsights.queue.push(function () {
appInsights.context.addTelemetryInitializer(versionInfoTelemetryInitialier);
});
but in your initializer you switched from context.application.ver in your first example, to context.component.version in your second.
the javascript SDK is documented on the github repo:
https://github.com/Microsoft/ApplicationInsights-JS/blob/master/API-reference.md
and the examples there show:
context.application.ver: string
context.application.build : string
so shouldn't that initializer method be:
function versionInfoTelemetryInitialier(envelope) {
var telemetryItem = envelope.data.baseData;
telemetry.context.application.ver = 'some version number';
}

Related

StackOverflowError when executing javascript function from java with graalvm

I know its a lot to ask to read such a big post but i hope you do as i really dont have any idea where to start looking for a solution of a problem that I dont even understand.
I have a java service on a windows server. This service loads/evaluates several javascript files at startup. Those javascript files all have the same structure, they contain two functions: process(name, content) { return { result: data } } and selfTest(). The server loads the script, evaluates it, checks for the reqiured functions, runs the selftest and stores the handle of the process function in a map (key for the map is the field name the script is executed on) if the selftest succeeds:
// Called on MainThread
private static final String JS_FN_SELFTEST = "selfTest";
private static final String JS_FN_PROCESS = "process";
private final Map<String, Value> _cache;
private final Context _ctx;
public ScriptManager () {
_cache = new HashMap<>();
_ctx = Context.newBuilder("js").allowIO(true).build();
}
private void addScriptFile(Path fileName, String... fieldNames)
throws IOException, NoSuchMethodException {
var p = Path.of(fileName.toString());
var jsSource = Files.readString(p);
var evaluated = _ctx.eval("js", jsSource);
if (!evaluated.hasMember(JS_FN_SELFTEST)) {
throw new NoSuchMethodException(JS_FN_SELFTEST);
}
var fnSelfTest = evaluated.getMember(JS_FN_SELFTEST);
fnSelfTest.execute();
if (!evaluated.hasMember(JS_FN_PROCESS)) {
throw new NoSuchMethodException(JS_FN_PROCESS);
}
for(String column: fieldNames) {
_cache.put(column, evaluated.getMember(JS_FN_PROCESS));
}
}
After startup the service watches a network share for file drops. when a file drops, the file will be read and processed. The data will be cleaned first with a generic script and then the fields that are part of the map will also be processed. The following function does the cleaning, the field-processing is similar and the problem occurs there too.
// Called on JobProcessingThread
public List<Data> clean(DataMap dataSet) {
var modified = new ArrayList<Data>();
var fnProcess = _cache.get(ALL_COLUMNS_MARKER);
for(var key: dataSet.keyList()) {
var data = dataSet.get(key);
if (!data.Field.Scriptable) continue;
String oldContent = data.getContent();
if (oldContent == null) continue;
try {
var value = fnProcess.execute(data.SourceName, oldContent); // error occurs here
var map = value.as(Map.class);
var newContent = map.get("result").toString();
if (!oldContent.equals(newContent)) {
data.setContent(newContent);
modified.add(data);
}
} catch(PolyglotException pe) {
data.setProblem(pe.getMessage());
}
}
return modified;
}
And finally this is one of the loaded scripts:
(function() {
function process(name, input) {
if (input === null) return { result: null };
let tmp = input.trim();
if (tmp.length === 0) return { result: null };
// some logic here
return {
result: result !== '' ? result : null
};
}
function selfTest() {
}
return { process, selfTest };
})();
Thats the scenario. When I run the app and drop a file I receive a StackOverflowError when the first scriptable field is processed in line fnProcess.execute(data.SourceName, oldContent); and The JVM is terminated (!). The script debugger of netbeans shows that this happens in the line let tmp = input.trim();. When i remove the trim() command the script will be executed until the next function call on a string (like indexOf) but the length check tmp.length === 0 will be executed normally (at least the netbeans debugger shows it like that). The problem occurs regardless of the string content passed, even hard coding strings generates the error in the server environment.
Uncaught exception exiting JVMCIEnv scope entered at c:\buildbot\worker\e\main\jdk\src\hotspot\share\jvmci\jvmciCompilerToVM.cpp:2386
Exception in thread "Thread-JobCenter": java.lang.StackOverflowError
java.lang.StackOverflowError
at com.oracle.svm.core.graal.snippets.StackOverflowCheckSnippets.newStackOverflowError0(StackOverflowCheckImpl.java:363)
at com.oracle.svm.core.graal.snippets.StackOverflowCheckSnippets.newStackOverflowError(StackOverflowCheckImpl.java:359)
at com.oracle.svm.core.graal.snippets.StackOverflowCheckSnippets.throwNewStackOverflowError(StackOverflowCheckImpl.java:339)
at com.oracle.svm.core.graal.jdk.ArraycopySnippets.boundsCheck(ArraycopySnippets.java:117)
at com.oracle.svm.core.graal.jdk.ArraycopySnippets.doArraycopy(ArraycopySnippets.java:94)
at java.util.Arrays.copyOf(Arrays.java:3539)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:228)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:802)
at java.lang.StringBuilder.append(StringBuilder.java:242)
at com.oracle.svm.core.util.Utf8.utf8ToString(Utf8.java:144)
at com.oracle.svm.core.util.Utf8.utf8ToString(Utf8.java:187)
at com.oracle.svm.jni.functions.JNIFunctions.NewStringUTF(JNIFunctions.java:479)
at jdk.vm.ci.hotspot.CompilerToVM.getResolvedJavaType0(CompilerToVM.java)
at jdk.vm.ci.hotspot.CompilerToVM.getResolvedJavaType(CompilerToVM.java:674)
at jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl.getHolder(HotSpotResolvedJavaMethodImpl.java:97)
at jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl.fromMetaspace(HotSpotResolvedJavaMethodImpl.java:115)
at com.oracle.svm.jni.JNIJavaCallWrappers.jniInvoke_VA_LIST:Ljdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl_2_0002efromMetaspace_00028J_00029Ljdk_vm_ci_hotspot_HotSpotResolvedJavaMethod_2(JNIJavaCallWrappers.java:0)
at org.graalvm.libgraal.jni.JNI$CallStaticObjectMethodA.call(JNI.java)
at org.graalvm.libgraal.jni.FromLibGraalCalls.callJObject(FromLibGraalCalls.java:153)
at org.graalvm.compiler.truffle.compiler.hotspot.libgraal.HSTruffleCompilerRuntimeGen.callGetTruffleCallBoundaryMethods(HSTruffleCompilerRuntimeGen.java:181)
at org.graalvm.compiler.truffle.compiler.hotspot.libgraal.HSTruffleCompilerRuntime.getTruffleCallBoundaryMethods(HSTruffleCompilerRuntime.java:356)
at org.graalvm.compiler.truffle.compiler.hotspot.HotSpotTruffleCompilerImpl.installTruffleCallBoundaryMethods(HotSpotTruffleCompilerImpl.java:216)
at org.graalvm.compiler.truffle.compiler.hotspot.libgraal.TruffleToLibGraalEntryPoints.installTruffleCallBoundaryMethods(TruffleToLibGraalEntryPoints.java:305)
#
# A fatal error has been detected by the Java Runtime Environment:
#
# Internal Error (jvmciRuntime.cpp:1215), pid=15740, tid=10088
# fatal error: Fatal exception in JVMCI: Uncaught exception exiting JVMCIEnv scope entered at c:\buildbot\worker\e\main\jdk\src\hotspot\share\jvmci\jvmciCompilerToVM.cpp:2386
#
# JRE version: OpenJDK Runtime Environment GraalVM CE 21.1.0 (16.0.1+9) (build 16.0.1+9-jvmci-21.1-b05)
# Java VM: OpenJDK 64-Bit Server VM GraalVM CE 21.1.0 (16.0.1+9-jvmci-21.1-b05, mixed mode, sharing, tiered, jvmci, jvmci compiler, compressed oops, compressed class ptrs, g1 gc, windows-amd64)
# No core dump will be written. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\Data\hs_err_pid15740.log
#
# If you would like to submit a bug report, please visit:
# https://github.com/oracle/graal/issues
#
This is part of the hs_err_pid15740.log
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j jdk.vm.ci.hotspot.CompilerToVM.translate(Ljava/lang/Object;)J+0 jdk.internal.vm.ci#16.0.1
j jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.translate(Ljava/lang/Object;)J+5 jdk.internal.vm.ci#16.0.1
j jdk.internal.reflect.GeneratedMethodAccessor4.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+40 java.base#16.0.1
j jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+6 java.base#16.0.1
j java.lang.reflect.Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+59 java.base#16.0.1
j org.graalvm.libgraal.LibGraal.translate(Ljava/lang/Object;)J+28 jdk.internal.vm.compiler
j org.graalvm.compiler.truffle.runtime.hotspot.libgraal.TruffleFromLibGraalEntryPoints.getTruffleCallBoundaryMethods(Ljava/lang/Object;)[J+122 jdk.internal.vm.compiler
v ~StubRoutines::call_stub
j org.graalvm.compiler.truffle.runtime.hotspot.libgraal.TruffleToLibGraalCalls.installTruffleCallBoundaryMethods(JJLorg/graalvm/compiler/truffle/common/CompilableTruffleAST;)V+0 jdk.internal.vm.compiler
j org.graalvm.compiler.truffle.runtime.hotspot.libgraal.LibGraalHotSpotTruffleCompiler.installTruffleCallBoundaryMethods(Lorg/graalvm/compiler/truffle/common/CompilableTruffleAST;)V+25 jdk.internal.vm.compiler
j org.graalvm.compiler.truffle.runtime.hotspot.AbstractHotSpotTruffleRuntime.bypassedInstalledCode(Lorg/graalvm/compiler/truffle/runtime/OptimizedCallTarget;)V+14 jdk.internal.vm.compiler
j org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.interpreterCall()Z+11 jdk.internal.vm.compiler
j org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.callBoundary([Ljava/lang/Object;)Ljava/lang/Object;+1 jdk.internal.vm.compiler
j org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.doInvoke([Ljava/lang/Object;)Ljava/lang/Object;+2 jdk.internal.vm.compiler
j org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.callBoundary([Ljava/lang/Object;)Ljava/lang/Object;+9 jdk.internal.vm.compiler
j org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.doInvoke([Ljava/lang/Object;)Ljava/lang/Object;+2 jdk.internal.vm.compiler
// repeated for about 8000 rows...
But when I ran the following code with the same script file as above and i pass the same arguments to the javascript function as the server would do when the file drops, no exception is thrown:
var ctx = Context.newBuilder("js").allowAllAccess(false).allowIO(true).build();
var js = java.nio.file.Files.readString(Path.of("scripts/0.js"));
var evaluated = ctx.eval("js", js);
var fn = evaluated.getMember("process");
var result = fn.execute("test", "some content ");
I hope someone survived the gigantic textwall and made it till here and can tell me what i am doing wrong...
I could solve the problem by upgrading GraalVM to version 22.2. Sadly, with this version, javascript support is not included anymore and have to be added with the console. Still have no idea what was wrong (and I am almost sure that the problem did not exist in the previous version).
This is not to credit myself. But because of the large text people might only look if there is an accepted answer and would not see an answer at the end of the text

Problems using promiseToFuture with an object coming from context.callmethod ()

As the title suggests, I am trying to use promiseToFuture (function of the dart library dart:js_util) on an object deriving from the method of DART:JS which is context.callmethod (''), whose objective is to perform a JavaScript function, which identifies through the string passed as a parameter; The code below:
void onWalletConnect() {
var promiseWallet =
await promiseToFuture(js.context.callMethod('JsConnectWallet'));
// ignore: avoid_print
print(promiseWallet);
if (promiseWallet['address'].compareTo('errorAddress') != 0) {
setState(() {
walletAddress = promiseWallet['address'];
isWalletconnect = true;
});
}
}
// "`js.context.callMethod('..')` Returns an Object Promise; "
Below the import:
import 'dart:js' as js;
import 'dart:js_util';
To the execution of promisetofutures() [and I am sure that this is the function that generates error and not the js.context.callMethod()] I get the following error from the Chrome console:
"
Uncaught (in promise) TypeError: js.Promise.then in not a function
at Object.promiseToFuture (js_util.dart:275:35)
at _first._MyHomePageState.new.OnWalletConnect (_first.dart:28:1)
"
I don't understand why you generate this error and how to solve it, can anyone help me?

WinRT - Starting/Registering IBackgroundTask in universal application

I would like to start my IBackgroundTask when my application starts up.
I have added my task to the .appxmanifest.xml file, and my extensions tag now looks like this
<Extensions>
<Extension Category="windows.backgroundTasks" EntryPoint="CordovaApp.Library.UploadTask">
<BackgroundTasks>
<Task Type="systemEvent" />
<Task Type="timer" />
</BackgroundTasks>
</Extension>
</Extensions>
My IBackgroundTask class is called UploadTask and is held in another project which has the outtype set to Windows Runtime Component.
Here is a cut down version of the code, so you can see the namespace etc
namespace CordovaApp.Library
{
public sealed class UploadTask : IBackgroundTask
{
public async void Run(IBackgroundTaskInstance taskInstance)
{
var connectionProfile = NetworkInformation.GetInternetConnectionProfile();
// connectionProfile can be null (e.g. airplane mode)
if (connectionProfile != null && connectionProfile.IsWlanConnectionProfile)
{
// custom code here
}
}
}
}
I have added a reference to this project to my universal runtime component project.
Everything builds fine.
Now to start the application, i guess i have to use WinJs, so i have the following code.
var uploadTaskName = 'UploadTask';
var tasks = Windows.ApplicationModel.Background.BackgroundTaskRegistration.allTasks;
var uploadTaskFound = false;
for (var i = 0; i < tasks.length; i++) {
if (tasks[i].Value.name == uploadTaskName) {
successCallback();
return;
}
}
Windows.ApplicationModel.Background.BackgroundExecutionManager.requestAccessAsync().then(function() {
var builder = new Windows.ApplicationModel.Background.BackgroundTaskBuilder();
builder.name = "Upload Task";
builder.taskEntryPoint = "CordovaApp.Library.UploadTask";
builder.setTrigger(new Windows.ApplicationModel.Background.TimeTrigger(15, false));
return builder.register();
}).done(function () {
successCallback();
}, function(err) {
errorCallback(err);
});
Now the requestAccessAsync method always throws an exception of
0x80004005 - JavaScript runtime error: Unspecified error
WinRT information: The application is not lock-screen capable.
Have a registered everything correctly? I am running this via Visual Studio 2013 on a laptop.
Seems that because the app was already installed, the permission was not given.
By uninstalling the application, and re-running it, i was then prompted to allow/disallow the background service to run. Checked allow, and now seems to work

"Sys is not defined" error when adding custom validation (MVC Foolproof validation)

I'm trying to add a custom validator using the MVC Foolproof library.
However, upon following the instructions here I get the error message "Sys is not defined".
I suspect this is because the library was originally written to work with the older validation script files which came with MVC 2 (and possibly 3), so is there a way to register my validation function for the javascript validation files which come with MVC 4?
The property on my model is defined as
[RatingTextRequired(ErrorMessageResourceType = typeof(ModelResources.Customer.Order.FeedbackRating), ErrorMessageResourceName = "RequiredError_Comment")]
public string FeedbackText { get; set; }
The validation attribute is defined as
public class RatingTextRequiredAttribute : ModelAwareValidationAttribute
{
//this is needed to register this attribute with foolproof's validator adapter
static RatingTextRequiredAttribute()
{
Register.Attribute(typeof (RatingTextRequiredAttribute));
}
public override bool IsValid(object value, object container)
{
var model = (Areas.Customer.Models.FeedbackRating) container;
return !(String.IsNullOrWhiteSpace(value.ToString()) && (model.WantsPostEditing || model.Rating == "0"));
}
}
And the JavaScript wiring-up for this is
Sys.Mvc.ValidatorRegistry.validators["ratingtextrequired"] = function (rule) {
return function(value, context) {
var wantsPostEditingProp = foolproof.getId(context.fieldContext.elements[0], "WantsPostEditing");
var wantsPostEditingVal = document.getElementById(wantsPostEditingProp).value;
var ratingProp = foolproof.getId(context.fieldContext.elements[0], "Rating");
var ratingVal = document.getElementById(ratingProp).value;
return !(value.length == 0 && (wantsPostEditingVal || ratingVal === "0"));
};
};
Also, I'm not sure what the file MvcFoolproofJQueryValidation.js is requied for because somehow I had the out-of-the-box validation working without this script file being present. Sadly, including it doesn't help with my "Sys is not defined" error.
Base on your error you are using the jquery obstructive approach.
See this post for more info.

MSScriptControl Issue on Windows Server 2008

So I'm using the MSScriptControl to run some javascript in my app and I want to be able to get some information about any errors the script may cause.
MSScriptControl.ScriptControlClass script = new MSScriptControl.ScriptControlClass();
try
{
script.Language = "JScript";
script.Timeout = 15000;
script.Eval(Code);
}
catch (Exception ex)
{
MSScriptControl.Error err = script.Error;
ret = new Exception("Error on line: " + err.Line + ", Description: " + err.Description);
}
The code works fine on my development machine, a Windows 7 box, and gives me a line number with an error. So I happily publish and push it to the production machine which always tells me the error occurred at line 0 and no description is provided.
I tried going to http://www.microsoft.com/download/en/details.aspx?id=1949 to download the latest version but installing it had no effect. I also set the property Embed Interop Types to false as well as copying my own msscript.ocx file into the Windows 2008 server's system32 directory but neither of these attempts resolved anything.
Anyone have any recommendations?
If you want to do it in all native c# without any 3rd party or "component" external dependencies use a CodeDomProvider with a tiny JScript bootstrap, like this:
private static readonly MethodInfo eval = CodeDomProvider
.CreateProvider("JScript")
.CompileAssemblyFromSource(new CompilerParameters(), "package e{class v{public static function e(e:String):Object{return eval(e);}}}")
.CompiledAssembly
.GetType("e.v")
.GetMethod("e");
private static object JsEval(string jscript)
{
try
{
return eval.Invoke(null, new[] { jscript });
}
catch (Exception ex)
{
return ex;
}
}
that creates a JsEval(string) method that you can use anywhere in your code to "eval" a string as JavaScript (well JScript)... So calling:
MessageBox.Show("" + JsEval("2 + 2")); // 4
MessageBox.Show("" + JsEval("(function(){ return 3+7; })();")); // 10
MessageBox.Show("" + JsEval("function yay(a) { return a + 1; } yay(2);")); // 3
depending on your use you may not want to instantiate these members statically. if you want to manipulate complex objects you will need create a wrapper to reflectively extract data (or you could cast as the appropriate JScript counterpart, but I've never tried this as you'd have to include the JScript assemblies).
here is an example of a wrapper class that does everything JavaScript will let you do natively, adding anymore high level functionality would probably be cumbersome enough so that you'd be better off either extracting the members into a dictionary / hash table OR alternatively serializing and deserializing on the other end
private class JsObjectWrapper : IEnumerable
{
public readonly object jsObject;
private static PropertyInfo itemAccessor = null;
private static MethodInfo getEnumerator = null;
public JsObjectWrapper(object jsObject)
{
this.jsObject = jsObject;
if (itemAccessor == null)
{
itemAccessor = jsObject.GetType().GetProperty("Item", new Type[] { typeof(string) });
}
if (getEnumerator == null)
{
getEnumerator = jsObject.GetType().GetInterface("IEnumerable").GetMethod("GetEnumerator");
}
}
public object this[string key]
{
get { return itemAccessor.GetValue(jsObject, new object[] { key }); }
set { itemAccessor.SetValue(jsObject, value, new object[] { key }); }
}
IEnumerator IEnumerable.GetEnumerator()
{
return (IEnumerator)getEnumerator.Invoke(jsObject, null);
}
}
you can see this in action by doing this:
var jsObj = JsEval("var x = { a:7, b:9 };");
var csObj = new JsObjectWrapper(jsObj);
MessageBox.Show("a: " + csObj["a"]); // a: 7
MessageBox.Show("b: " + csObj["b"]); // b: 9
csObj["yay!"] = 69;
foreach (string key in csObj)
{
MessageBox.Show("" + key + ": " + csObj[key]); // "key": "value"
}
i personally have used code similar to this to great effect at one point or another and can vouch for it's availability and runnability inside a server environment.. I hope this helps -ck
Regarding the problem you face just some thoughts:
according to the link you provided this control neither supports Windows 7 nor Windows 2008
it might be a security issue with regards to COM/UAC etc.
it might be a problem because of bitness if you compiled for AnyCPU, try using x86
Regarding possible alternatives:
Using JScript you can build an evaluator rather easily which is supported anywhere .NET 4 runs (including Windows Server 2008).
Using JInt as a JavaScript interpreter

Categories

Resources