View event details in Firebase - firebase

I am sending app usage analytics events to Fabric and Firebase. Together with the event, I am also sending another value (an example event type is font_selection and the value I pass is which font the user selects - this is a number that tells me which font was used). I was using Fabric events and I could see which fonts were being used more or less when I selected the font_selection event (I could see numbers for each different font).
Since the Fabric functionality is being moved to Firebase, I started checking the Analytics section in Firebase. Unfortunately I cannot find the above information in Firebase > Analytics > Events. I can see the event, font_selection but when I click on it I do not get the additional information I used to get in Fabric. Is there something I am missing or has this additional information been removed from Firebase?

This is still an issue for me. Here is how I'm sending the event into Firebase:
protected void Report(string id, Severity severity, string message = null, Exception exception = null)
{
try
{
var processedId = id ?? severity.ToString().ToLowerInvariant();
var values = new Dictionary<string, string>();
values.Add("severity", severity.ToString().ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(message))
{
values.Add("message", message);
}
if (exception != null)
{
values.Add("exception", exception.Message);
values.Add("trace", exception.StackTrace);
}
SendEvent(values, processedId);
}
catch
{
// do nothing.
}
}
protected override void SendEvent(Dictionary<string, string> eventData, string id)
{
var firebaseAnalytics = FirebaseAnalytics.GetInstance(Android.App.Application.Context);
var bundle = new Android.OS.Bundle();
foreach(var pair in eventData)
{
bundle.PutString(pair.Key, pair.Value);
}
firebaseAnalytics.LogEvent(id, bundle);
}
During runtime, I call this successfully and I can see these event popping up in Firebase console:
But how do I display the rest of the properties that I have bundled with it? Here is what the console shows me in events:
I feel like I must be using it wrong or something. There is no UI to shows me a simple chronologically sorted table with events as they came in with properties they came with. I frankly don't understand what good is this tool to me.

Related

Azure Function Integration of Serilog with Application Insights, logs visible in Search but are not appearing in Failures events timeline

I am trying to use Serilog with Application Insights sink for logging purposes. I can see the logs in Search bar in Azure Portal (Application Insights) but same logs are not visible if we view the timeline of events in Failures or Performance Tab. Thanks
Below is the code am using for registering Logger in FunctionStartup, which then gets injected in Function for logging:
var logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.Enrich.WithProperty("ApplicationName", "testApp")
.Enrich.WithProperty("Environment", "Dev")
.WriteTo.ApplicationInsights(GetTelemetryClient("Instrumentationkey"), TelemetryConverter.Traces)
.CreateLogger();
builder.Services.AddSingleton<ILogger>(logger);
Telementory Client is getting fetched from a helper method:
public static TelemetryClient GetTelemetryClient(string key)
{
var teleConfig = new TelemetryConfiguration { InstrumentationKey = key };
var teleClient = new TelemetryClient(teleConfig);
return teleClient;
}
host.json
{
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingExcludedTypes": "Request",
"samplingSettings": {
"isEnabled": true
}
}
}
}
I got your mean, and pls allow me to sum up my testing result here.
First, the failure blade is not designed for providing a timeline which used to trace the details(what happened before the exception take place), but to show all the exceptions, how often the error happened, how many users be affected, etc, it's more likely stand in a high place to see the whole program.
And to achieve your goal, I think you can use this kql query in the Logs blade or watching it in transaction blade.
union traces, requests,exceptions
| where operation_Id == "178845c426975d4eb96ba5f7b5f376e1"
Basically, we may add many logs in the executing chain, e.g. in the controller, log the input parameter, then log the result of data combining or formatting, log the exception information in catch, so here's my testing code. I can't see any other information in failure blade as you, but in the transaction blade, I can see the timeline.
public class HelloController : Controller
{
public string greet(string name)
{
Log.Verbose("come to greet function");
Log.Debug("serilog_debug_info");
Log.Information("greet name input " + name);
int count = int.Parse(name);
Log.Warning("enter greet name is : {0}", count);
return "hello " + name;
}
}
And we can easily find that, the whole chain shares the same operationId, and via all these logs, we can pinpoint the wrong line code. By the way, if I surround the code with try/catch, exception won't be captured in the failure blade.
==================================
Using Serilog integrate app insights, we need to send serilog to application insights, and we will see lots of Traces in transaction search, so it's better to made the MinimumLevel to be information and higher. The sreenshot below is my log details, and we can also use kql query by operationId to see the whole chain.
You can easily solve this by following the solution provided by Azure Application Insights on their GitHub repo, as per this Github Issue, you can either use the DI to configure TelemetryConfiguration, i.e
services.Configure<TelemetryConfiguration>(
(o) => {
o.InstrumentationKey = "123";
o.TelemetryInitializers.Add(new OperationCorrelationTelemetryInitializer());
});
or you can configure it manually like this:
var config = TelemetryConfiguration.CreateDefault();
var client = new TelemetryClient(config);
So in your code, you have to change your GetTelemetryClient from
public static TelemetryClient GetTelemetryClient(string key)
{
var teleConfig = new TelemetryConfiguration { InstrumentationKey = key };
var teleClient = new TelemetryClient(teleConfig);
return teleClient;
}
to this
public static TelemetryClient GetTelemetryClient(string key)
{
var teleConfig = TelemetryConfiguration.CreateDefault();
var teleClient = new TelemetryClient(teleConfig);
return teleClient;
}
In order to use logging using Telemetry Configuration as mentioned in the answer above for Azure Functions, we just need to update the function as in below snippet and on deployment it should fetch Instrumentation key itself
public static TelemetryClient GetTelemetryClient()
{
var teleConfig = TelemetryConfiguration.CreateDefault();
var teleClient = new TelemetryClient(teleConfig);
return teleClient;
}
But to run both locally and after deployment on Azure. We need to add something like this in function Startup and get rid of the Function above.
builder.Services.Configure<TelemetryConfiguration>((o) =>
{
o.InstrumentationKey = "KEY";
o.TelemetryInitializers.Add(new OperationCorrelationTelemetryInitializer());
});
builder.Services.AddSingleton<ILogger>(sp =>
{
var logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.Enrich.WithProperty("ApplicationName", "TEST")
.Enrich.WithProperty("Environment", "DEV")
.WriteTo.ApplicationInsights(
sp.GetRequiredService<TelemetryConfiguration>(), TelemetryConverter.Traces).CreateLogger();
return logger;
});
After wards we just need to use typical DI in our classes/azure function to use ILogger
public class Test{
public ILogger _log;
public void Test(ILogger log){
_log=log;
}
}

Unity: Receive Firebase Short Dynamic Link in DynamicLinkReceived callback event

I would like to use Firebase Dynamic Links for Unity (Android/iOS) so users can invite friends and be rewarded with.
Each user gets a different Short Dynamic Link in the form of https://test.page.link/abcd
The user can share this Short DynamicLink with friends.
When the invited friend comes into the app, this callback is called.
private void OnDynamicLink(object sender, EventArgs args) {
var dynamicLinkEventArgs = args as ReceivedDynamicLinkEventArgs;
Debug.LogFormat("Received dynamic link {0}",
dynamicLinkEventArgs.ReceivedDynamicLink.Url.OriginalString);
}
Unfortunately, I only get back the base link that was necessary to create the short dynamic link.
Received dynamic link https://www.example.com/referral?xxxxxxxxxx
I get an additional native output in my iOS app:
IOSNative::Native->Unity callback data:
{"m_EventName":"continueUserActivity","m_Data":"https://test.page.link/?link=https://www.example.com/referral?xxxxxxxxxx&apn=de.test.testapp&isi=123456789&ibi=de.test.testapp&cid=1579347010984123886&_osl=https://test.page.link/abcd&_fpb=AB6327276CFGHT==&_cpt=cpit&_iumenbl=1&_iumchkactval=1&_plt=2076&_uit=2692&_cpb=1"}
2020-01-14 15:30:20.455009+0100 ambassador[315:8406]
IOSNative::Native->Unity callback data:
{"m_EventName":"applicationDidBecomeActive","m_Data":""}
Now my question is how do I get the generated short dynamic link that I have shared with a friend in OnDynamicLink callback( https://test.page.link/abcd)?
I need the value behind the parameter "&_osl" as seen in additional native output. But I only get the Base Url back in Unity (https://www.example.com/referral?xxxxxxxxxx).
My solution at the end was to shorten the BaseLink with the help of DynamicLinks.GetShortLinkAsync.
//unescape url
baseLink = UnityEngine.Networking.UnityWebRequest.UnEscapeURL(baseLink);
var components = new DynamicLinkComponents(
// The base Link.
new Uri(baseLink),
// The dynamic link URI prefix.
domainUriPrefix) {
IOSParameters = new IOSParameters(PackageName) {
AppStoreId = "XXXXXXXXX"
},
AndroidParameters = new AndroidParameters(PackeName)
};
string inviteLink = string.Empty;
await DynamicLinks.GetShortLinkAsync(components, options).ContinueWith((task) => {
if (task.IsCanceled) {
Debug.LogError("GetShortLinkAsync was canceled.");
return;
}
if (task.IsFaulted) {
Debug.LogError("GetShortLinkAsync encountered an error: " + task.Exception);
return;
}
// Short Link has been created.
inviteLink = task.Result.Url.ToString();
});

Adding a location that is tied to a userID via Foreign Key

I'm learning .NET here and have build a small API that allows me to register users, retrieve user lists, or a single user, as well as edit them. Microsoft Identity is used for most of this process.
I am now trying to add new section to this API that will handle physical locations. Each location will be tied back to a specific user, so there may be one or multiple locations per user. I'm having trouble building this part of it though. I cant seem to figure out how to tie the ID of the user to the location as a foreign key. I've been battling this one now for quite some time.
I have the controller build for the location calls, and the DTO's, but it does not seem to want to actually work correctly.
Anyone up to talking a look and letting me know what needs to be done and how to do this? I'm a bit lost and really wanting to learn how this works. The github repo with the full working project is here:
https://github.com/sapper6fd/API
The issue at hand here was the way it was configured.
The following adjustments fixed the issue:
CreateLocation() method:
[HttpPost]
public async Task<IActionResult> CreateLocation(int clientId, LocationCreateDto locationCreateDto)
{
// Grab the current users roles to verify they have access to this API call
var userRole = User.FindFirst(ClaimTypes.Role).ToString();
if (userRole != "http://schemas.microsoft.com/ws/2008/06/identity/claims/role: GlobalAdmin")
return Unauthorized();
// Create the new location
var newLocation = _mapper.Map<Locations>(locationCreateDto);
_repo.Add(newLocation);
if (await _repo.SaveAll())
{
var locationToReturn = _mapper.Map<LocationCreateDto>(newLocation);
return CreatedAtRoute(nameof(GetLocation), new { id = locationToReturn.Id, userid=clientId }, locationToReturn);
}
throw new Exception("Unable to create new location. Failed to save.");
}
HttpGet Method:
[HttpGet("{id}", Name = nameof(GetLocation))]
public async Task<IActionResult> GetLocation(int id)
{
var location = await _repo.GetLocation(id);
var locationToReturn = _mapper.Map<LocationCreateDto>(location);
return Ok(locationToReturn);
}

IAP items not showing using the Xamarin IAP nuget package

I have two IAPs set up on for my iOS app on iTunes Connect. All of the information is in there and they marry up to what I have set for Android. On iTunes, they are set as non-renewing subscriptions (mainly as this is what the review said they should be). There are no errors shown on the IAP screen and have been submitted for review (this makes no difference, the ones I had there previously didn't show either)
I'm using the Xamarin In App Purchase nuget package to get this working. When I run the app on Android, the packages show correctly. When I run the same code on iOS, nothing is showing.
I have a user set on the sandbox and have followed the instructions on the iTunes website on logging out of the store, but I'm seeing nothing - it's not even asking me to log into the store.
My code for interrogating the store is this
async Task<List<InAppBillingProduct>> GetItems()
{
var billing = CrossInAppBilling.Current;
try
{
var productIds = new string[] { "monthly_renewals", "yearly_subscriptions" };
//You must connect
var connected = await billing.ConnectAsync();
if (!connected)
{
//Couldn't connect
return new List<InAppBillingProduct>();
}
//check purchases
var items = await billing.GetProductInfoAsync(ItemType.Subscription, productIds);
return items.ToList();
}
catch (InAppBillingPurchaseException)
{
return new List<InAppBillingProduct>();
}
catch (Exception)
{
return new List<InAppBillingProduct>();
}
finally
{
await billing.DisconnectAsync();
}
}
It makes no difference if I set the ItemType to Subscription or InAppPurchase. All of the licences on iTunesConnect are correct, IAP is set to work in the provisioning profile too.
Given the store isn't asking for a login for the sandbox user, I'm wondering if something else needs to be done - I just don't know what.

SignalR recording when a Web Page has closed

I am using MassTransit request and response with SignalR. The web site makes a request to a windows service that creates a file. When the file has been created the windows service will send a response message back to the web site. The web site will open the file and make it available for the users to see. I want to handle the scenario where the user closes the web page before the file is created. In that case I want the created file to be emailed to them.
Regardless of whether the user has closed the web page or not, the message handler for the response message will be run. What I want to be able to do is have some way of knowing within the response message handler that the web page has been closed. This is what I have done already. It doesnt work but it does illustrate my thinking. On the web page I have
$(window).unload(function () {
if (event.clientY < 0) {
// $.connection.hub.stop();
$.connection.exportcreate.setIsDisconnected();
}
});
exportcreate is my Hub name. In setIsDisconnected would I set a property on Caller? Lets say I successfully set a property to indicate that the web page has been closed. How do I find out that value in the response message handler. This is what it does now
protected void BasicResponseHandler(BasicResponse message)
{
string groupName = CorrelationIdGroupName(message.CorrelationId);
GetClients()[groupName].display(message.ExportGuid);
}
private static dynamic GetClients()
{
return AspNetHost.DependencyResolver.Resolve<IConnectionManager>().GetClients<ExportCreateHub>();
}
I am using the message correlation id as a group. Now for me the ExportGuid on the message is very important. That is used to identify the file. So if I am going to email the created file I have to do it within the response handler because I need the ExportGuid value. If I did store a value on Caller in my hub for the web page close, how would I access it in the response handler.
Just in case you need to know. display is defined on the web page as
exportCreate.display = function (guid) {
setTimeout(function () {
top.location.href = 'GetExport.ashx?guid=' + guid;
}, 500);
};
GetExport.ashx opens the file and returns it as a response.
Thank you,
Regards Ben
I think a better bet would be to implement proper connection handling. Specifically, have your hub implementing IDisconnect and IConnected. You would then have a mapping of connectionId to document Guid.
public Task Connect()
{
connectionManager.MapConnectionToUser(Context.ConnectionId, Context.User.Name);
}
public Task Disconnect()
{
var connectionId = Context.ConnectionId;
var docId = connectionManager.LookupDocumentId(connectionId);
if (docId != Guid.Empty)
{
var userName = connectionManager.GetUserFromConnectionId(connectionId);
var user = userRepository.GetUserByUserName(userName);
bus.Publish( new EmailDocumentToUserCommand(docId, user.Email));
}
}
// Call from client
public void GenerateDocument(ClientParameters docParameters)
{
var docId = Guid.NewGuid();
connectionManager.MapDocumentIdToConnection(Context.ConnectionId, docId);
var command = new CreateDocumentCommand(docParameters);
command.Correlationid = docId;
bus.Publish(command);
Caller.creatingDocument(docId);
}
// Acknowledge you got the doc.
// Call this from the display method on the client.
// If this is not called, the disconnect method will handle sending
// by email.
public void Ack(Guid docId)
{
connectionManager.UnmapDocumentFromConnectionId(connectionId, docId);
Caller.sendMessage("ok");
}
Of course this is from the top of my head.

Resources