Skip to content

Commit

Permalink
Release 1.1.0 (#35)
Browse files Browse the repository at this point in the history
* fix: Analytics controller is not initialized when activity resumes in MAUI Android

* feat:added backgroundReporting and NewEventSystem Configuration

* Feat:Added log forwarding and applicationExitInfo feature
  • Loading branch information
ndesai-newrelic authored Jul 18, 2024
1 parent 0bb3b5c commit 5552b0a
Show file tree
Hide file tree
Showing 41 changed files with 1,590 additions and 514 deletions.
25 changes: 23 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,31 @@
# Changelog


# 1.1.0


# Release Notes

## New Features

1. Application Exit Information
- Added ApplicationExitInfo to data reporting
- Enabled by default

2. Log Forwarding to New Relic
- Implement static API for sending logs to New Relic
- Can be enabled/disabled in your mobile application's entity settings page

## Improvements

- Native Android agent updated to version 7.5.0
- Native iOS agent updated to version 7.5.0

# 1.0.0

* Improvements

The native iOS Agent has been updated to version 7.4.12, bringing performance enhancements and bug fixes.
The native iOS Agent has been updated to version 7.4.11, bringing performance enhancements and bug fixes.

* New Features

Expand Down Expand Up @@ -59,4 +80,4 @@ The mobile agent team is proud to announce GA support for our .NET MAUI agent!
- Capture C# errors and crashes to quickly identify and fix problems
- Track network requests to see how your app is interacting with the backend
- Use distributed tracing to drill down into handled exceptions and identify the root cause of problems
- Create custom tracking events and metrics to fully understand how your users are interacting with your app
- Create custom tracking events and metrics to fully understand how your users are interacting with your app
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<Authors>New Relic</Authors>
<PackageTags>newrelic;MAUI;android;new relic;observability;monitoring;telemetry</PackageTags>
<Version>7.3.2</Version>
<Version>7.5.0</Version>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>
Expand Down
10 changes: 5 additions & 5 deletions NewRelic.MAUI.Plugin/NewRelic.MAUI.Plugin.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<SingleProject>true</SingleProject>
<ImplicitUsings>enable</ImplicitUsings>
<PackageId>NewRelic.MAUI.Plugin</PackageId>
<Version>1.0.0</Version>
<Version>1.1.0</Version>
<Summary>New Relic Plugin for .NET MAUI mobile apps</Summary>
<Description>With the New Relic .NET MAUI mobile plugin, your team can monitor the performance of .NET MAUI apps and identify code errors. The plugin collects crash data, network traffic, and other information for your apps using native components.</Description>
<Authors>New Relic</Authors>
Expand All @@ -31,10 +31,10 @@
<ItemGroup>
<Folder Include="Shared\" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0-ios'">
<PackageReference Include="NewRelic.MAUI.iOS.Binding" Version="7.4.12" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0-android'">
<PackageReference Include="NewRelic.MAUI.Android.Binding" Version="7.3.2" />
<PackageReference Include="NewRelic.MAUI.Android.Binding" Version="7.5.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0-ios'">
<PackageReference Include="NewRelic.MAUI.iOS.Binding" Version="7.5.0" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

using Com.Newrelic.Agent.Android.Distributedtracing;
using NRAndroidAgent = Com.Newrelic.Agent.Android.NewRelic;
using HeaderList = Com.Newrelic.Agent.Android.HttpHeaders;
Expand Down
175 changes: 132 additions & 43 deletions NewRelic.MAUI.Plugin/Platforms/Android/NewRelicMethodsImplementation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
*/

using Android.Runtime;
using Com.Newrelic.Agent.Android.Logging;
using NRAndroidAgent = Com.Newrelic.Agent.Android.NewRelic;
using NRNetworkFailure = Com.Newrelic.Agent.Android.Util.NetworkFailure;
using NRMetricUnit = Com.Newrelic.Agent.Android.Metric.MetricUnit;
using NRLogLevel = Com.Newrelic.Agent.Android.Logging.LogLevel;

namespace NewRelic.MAUI.Plugin;

Expand Down Expand Up @@ -110,9 +112,21 @@ public void Start(string applicationToken, AgentStartConfiguration agentConfig =
{
NRAndroidAgent.DisableFeature(Com.Newrelic.Agent.Android.FeatureFlag.OfflineStorage);
}

if (agentConfig.backgroundReportingEnabled)
{
NRAndroidAgent.EnableFeature(Com.Newrelic.Agent.Android.FeatureFlag.BackgroundReporting);
}
else
{
NRAndroidAgent.DisableFeature(Com.Newrelic.Agent.Android.FeatureFlag.BackgroundReporting);
}




var newRelic = NRAndroidAgent.WithApplicationToken(applicationToken)
.WithApplicationFramework(Com.Newrelic.Agent.Android.ApplicationFramework.Maui, "0.0.6")
.WithApplicationFramework(Com.Newrelic.Agent.Android.ApplicationFramework.Maui, "1.1.0")
.WithLoggingEnabled(agentConfig.loggingEnabled)
.WithLogLevel(logLevelDict[agentConfig.logLevel]);

Expand Down Expand Up @@ -149,29 +163,12 @@ public string CurrentSessionId()

public bool RecordBreadcrumb(string name, Dictionary<string, object> attributes)
{
Dictionary<string, Java.Lang.Object> strToJavaObject = new Dictionary<string, Java.Lang.Object>();
foreach (KeyValuePair<string, object> entry in attributes)
{
if (entry.Value is bool)
{
strToJavaObject.Add(entry.Key, (bool)entry.Value);
}
else if (IsNumeric(entry.Value))
{
strToJavaObject.Add(entry.Key, Convert.ToDouble(entry.Value));
}
else
{
strToJavaObject.Add(entry.Key, entry.Value.ToString());
}
}
return NRAndroidAgent.RecordBreadcrumb(name, strToJavaObject);
return NRAndroidAgent.RecordBreadcrumb(name, ConvertAttributesToJavaObjects(attributes));
}

public void EndInteraction(string interactionId)
{
NRAndroidAgent.EndInteraction(interactionId);
return;
}

public bool IncrementAttribute(string name, float value = 1)
Expand All @@ -182,52 +179,31 @@ public bool IncrementAttribute(string name, float value = 1)
public void NoticeHttpTransaction(string url, string httpMethod, int statusCode, long startTime, long endTime, long bytesSent, long bytesReceived, string responseBody)
{
NRAndroidAgent.NoticeHttpTransaction(url, httpMethod, statusCode, startTime, endTime, bytesSent, bytesReceived, responseBody);
return;
}

public void NoticeNetworkFailure(string url, string httpMethod, long startTime, long endTime, NetworkFailure failure)
{
NRAndroidAgent.NoticeNetworkFailure(url, httpMethod, startTime, endTime, networkFailureDict[failure]);
return;
}

public bool RecordCustomEvent(string eventType, string eventName, Dictionary<string, object> attributes)
{
Dictionary<string, Java.Lang.Object> strToJavaObject = new Dictionary<string, Java.Lang.Object>();
foreach (KeyValuePair<string, object> entry in attributes)
{
if (entry.Value is bool)
{
strToJavaObject.Add(entry.Key, (bool)entry.Value);
}
else if (IsNumeric(entry.Value))
{
strToJavaObject.Add(entry.Key, Convert.ToDouble(entry.Value));
}
else
{
strToJavaObject.Add(entry.Key, entry.Value.ToString());
}
}
return NRAndroidAgent.RecordCustomEvent(eventType, eventName, strToJavaObject);
return NRAndroidAgent.RecordCustomEvent(eventType, eventName, ConvertAttributesToJavaObjects(attributes));
}

public void RecordMetric(string name, string category)
{
NRAndroidAgent.RecordMetric(name, category);
return;
}

public void RecordMetric(string name, string category, double value)
{
NRAndroidAgent.RecordMetric(name, category, value);
return;
}

public void RecordMetric(string name, string category, double value, MetricUnit countUnit, MetricUnit valueUnit)
{
NRAndroidAgent.RecordMetric(name, category, 0, value, 0, metricUnitDict[countUnit], metricUnitDict[valueUnit]);
return;
}

public bool RemoveAllAttributes()
Expand Down Expand Up @@ -335,9 +311,10 @@ public void HttpResponseBodyCaptureEnabled(bool enabled)
return;
}

public HttpMessageHandler GetHttpMessageHandler()
public HttpClientHandler GetHttpMessageHandler()
{
var handler = new NewRelicHttpClientHandler();


//handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
//{
Expand Down Expand Up @@ -390,11 +367,103 @@ public void TrackShellNavigatedEvents()
public void Shutdown()
{
NRAndroidAgent.Shutdown();
return;
}

public void LogInfo(String message)
{
if (!string.IsNullOrEmpty(message))
{
NRAndroidAgent.LogInfo(message);
}
else
{
Console.WriteLine("Info: Message is empty or null.");
}
}

public void LogWarning(String message)
{
if (!string.IsNullOrEmpty(message))
{
NRAndroidAgent.LogWarning(message);
}
else
{
Console.WriteLine("Warning: Message is empty or null.");
}
}

public void LogDebug(String message)
{
if (!string.IsNullOrEmpty(message))
{
NRAndroidAgent.LogDebug(message);
}
else
{
Console.WriteLine("Debug: Message is empty or null.");
}
}

public void LogVerbose(String message)
{
if (!string.IsNullOrEmpty(message))
{
NRAndroidAgent.LogVerbose(message);
}
else
{
Console.WriteLine("Verbose: Message is empty or null.");
}
}

public void LogError(String message)
{
if (!string.IsNullOrEmpty(message))
{
NRAndroidAgent.LogError(message);
}
else
{
Console.WriteLine("Error: Message is empty or null.");
}
}

public void Log(LogLevel level, String message)
{
if (!string.IsNullOrEmpty(message))
{
NRLogLevel logLevel = level switch
{
LogLevel.INFO => NRLogLevel.Info,
LogLevel.AUDIT => NRLogLevel.Verbose,
LogLevel.ERROR => NRLogLevel.Error,
LogLevel.VERBOSE => NRLogLevel.Verbose,
LogLevel.WARNING => NRLogLevel.Warn,
_ => NRLogLevel.Error
};
NRAndroidAgent.Log(logLevel, message);
}
else
{
Console.WriteLine($"Log Level {level}: Message is empty or null.");
}
}



public void LogAttributes(Dictionary<string, object> attributes)
{
if(attributes != null && attributes.Count > 0)
{
NRAndroidAgent.LogAttributes(ConvertAttributesToJavaObjects(attributes));
}
else
{
Console.WriteLine("Attributes are empty or null.");
}
}

public void Dispose()
{
throw new NotImplementedException();
Expand All @@ -410,6 +479,26 @@ public List<string> GetHTTPHeadersTrackingFor()
return Com.Newrelic.Agent.Android.HttpHeaders.Instance.GetHttpHeaders().ToList();
}

public Dictionary<string, Java.Lang.Object> ConvertAttributesToJavaObjects(Dictionary<string, object> attributes)
{
Dictionary<string, Java.Lang.Object> strToJavaObject = new Dictionary<string, Java.Lang.Object>();
foreach (KeyValuePair<string, object> entry in attributes)
{
if (entry.Value is bool)
{
strToJavaObject.Add(entry.Key, (bool)entry.Value);
}
else if (IsNumeric(entry.Value))
{
strToJavaObject.Add(entry.Key, Convert.ToDouble(entry.Value));
}
else
{
strToJavaObject.Add(entry.Key, entry.Value.ToString());
}
}
return strToJavaObject;
}

}

Loading

0 comments on commit 5552b0a

Please sign in to comment.