Skip to content

Commit 8bf27ae

Browse files
committed
update csharp integration guide
1 parent 21a4d5c commit 8bf27ae

File tree

1 file changed

+245
-18
lines changed
  • src/connections/sources/catalog/libraries/server/csharp

1 file changed

+245
-18
lines changed

src/connections/sources/catalog/libraries/server/csharp/index.md

Lines changed: 245 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ redirect_from:
99

1010
With Analytics-CSharp, you can add Segment analytics to your C# based app which includes Unity, Xamarin, .NET. Analytics-CSharp helps you measure your users, product, and business. It unlocks insights into your app's funnel, core business metrics, and whether you have product-market fit. The Analytics-CSharp library is open-source [on GitHub](https://github.com/segmentio/analytics-csharp){:target="_blank"}.
1111

12-
> info ""
13-
> This library is currently in beta and is governed by Segment’s [First Access and Beta terms](https://www.twilio.com/legal/tos){:target="_blank"}.
1412

1513
### Supported platforms
1614
These platforms support Analytics-CSharp:
@@ -49,23 +47,24 @@ To get started with the Analytics-CSharp library:
4947
// NOTE: to make Analytics stateless/in-memory,
5048
// add `InMemoryStorageProvider` to the configuration
5149
var configuration = new Configuration("<YOUR WRITE KEY>",
52-
flushAt: 1,
53-
flushInterval: 10);
50+
flushAt: 20,
51+
flushInterval: 30);
5452
var analytics = new Analytics(configuration);
5553
```
5654
57-
These are the options you can apply to configure the client:
58-
59-
Option Name | Description
60-
----------- | -----------
61-
`writeKey` *required* | This is your Segment write key.
62-
`apiHost` | The default is set to `api.segment.io/v1`. <br> This sets a default API Host to which Segment sends events.
63-
`autoAddSegmentDestination` | The default is set to `true`. <br> This automatically adds the Segment Destination plugin. You can set this to `false` if you want to manually add the Segment Destination plugin.
64-
`defaultSettings` | The default is set to `{}`. <br> The settings object used as fallback in case of network failure.
65-
`flushAt` | The default is set to `20`. <br> The count of events at which Segment flushes events.
66-
`flushInterval` | The default is set to `30` seconds. <br> The interval in seconds at which Segment flushes events.
67-
`exceptionHandler` | Use to set an exception handler to handle errors happened in async methods within the analytics scope.
68-
`storageProvider` | Use to set how you want your data to be stored. <br> `DefaultStorageProvider` is used by default which stores data to local storage. `InMemoryStorageProvider` is also provided in the library. You can also write your own storage solution by implementing `IStorageProvider` and `IStorage`.
55+
| Option Name | Description |
56+
|-----------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
57+
| `writeKey` *required* | This is your Segment write key. |
58+
| `flushAt` | Default set to `20`. <br> The count of events at which Segment flushes events. |
59+
| `flushInterval` | Default set to `30` (seconds). <br> The interval in seconds at which Segment flushes events. |
60+
| `defaultSettings` | Default set to `{}`. <br> The settings object used as fallback in case of network failure. |
61+
| `autoAddSegmentDestination` | Default set to `true`. <br> This automatically adds the Segment Destination plugin. You can set this to `false` if you want to manually add the Segment Destination plugin. |
62+
| `apiHost` | Default set to `api.segment.io/v1`. <br> This sets a default API Host to which Segment sends events. |
63+
| `cdnHost` | Default set to `cdn-settings.segment.com/v1`. <br> This set a default cdnHost to which Segment fetches settings. |
64+
| `analyticsErrorHandler` | Default set to `null`. <br>This set an error handler to handle errors happened in analytics |
65+
| `storageProvider` | Default set to `DefaultStorageProvider`. <br>This set how you want your data to be stored. <br> `DefaultStorageProvider` is used by default which stores data to local storage. `InMemoryStorageProvider` is also provided in the library. <br>You can also write your own storage solution by implementing `IStorageProvider` and `IStorage` |
66+
| `httpClientProvider` | Default set to `DefaultHTTPClientProvider`. <br>This set a http client provider for analytics use to do network activities. The default provider uses System.Net.Http for network activities. |
67+
| `flushPolicies` | Default set to `null`. <br>This set custom flush policies to tell analytics when and how to flush. By default, it converts `flushAt` and `flushInterval` to `CountFlushPolicy` and `FrequencyFlushPolicy`. If a value is given, it overwrites `flushAt` and `flushInterval`. |
6968
7069
## Tracking Methods
7170
@@ -323,7 +322,213 @@ The `reset` method clears the SDK’s internal stores for the current user and g
323322
analytics.Reset()
324323
```
325324

326-
## Arrays
325+
326+
## Controlling Upload With Flush Policies
327+
To more granularly control when events are uploaded you can use `FlushPolicies`. **This will override any setting on `flushAt` and `flushInterval`, but you can use `CountFlushPolicy` and `FrequencyFlushPolicy` to have the same behaviour respectively.**
328+
329+
A Flush Policy defines the strategy for deciding when to flush, this can be on an interval, on a certain time of day, after receiving a certain number of events or even after receiving a particular event. This gives you even more flexibility on when to send event to Segment.
330+
331+
To make use of flush policies you can set them in the configuration of the client:
332+
```csharp
333+
var configuration = new Configuration("<YOUR WRITE KEY>",
334+
flushPolicies: new List<IFlushPolicy>
335+
{
336+
new CountFlushPolicy(),
337+
new FrequencyFlushPolicy(),
338+
new StartupFlushPolicy()
339+
});
340+
var analytics = new Analytics(configuration);
341+
```
342+
343+
That means only the first policy to reach `ShouldFlush` gets to trigger a flush at a time. In the example above either the event count gets to 5 or the timer reaches 500ms, whatever comes first will trigger a flush.
344+
345+
We have several standard FlushPolicies:
346+
- `CountFlushPolicy` triggers whenever a certain number of events is reached
347+
- `FrequencyFlushPolicy` triggers on an interval of milliseconds
348+
- `StartupFlushPolicy` triggers on client startup only
349+
350+
### Adding or removing policies
351+
352+
One of the main advantages of FlushPolicies is that you can add and remove policies on the fly. This is very powerful when you want to reduce or increase the amount of flushes.
353+
354+
For example you might want to disable flushes if you detect the user has no network:
355+
```csharp
356+
// listen to network changes
357+
if (noNetwork) {
358+
// remove all flush policies to avoid flushing
359+
analytics.ClearFlushPolicies();
360+
361+
// or disable analytics completely (including store events)
362+
analytics.Enable = false
363+
}
364+
else {
365+
analytics.AddFlushPolicy(new CountFlushPolicy(), new FrequencyFlushPolicy());
366+
}
367+
```
368+
369+
### Creating your own flush policies
370+
371+
You can create a custom FlushPolicy special for your application needs by implementing the `IFlushPolicy` interface. You can also extend the `FlushPolicyBase` class that already creates and handles the `shouldFlush` value reset.
372+
373+
A `FlushPolicy` only needs to implement 2 methods:
374+
- `Schedule`: Executed when the flush policy is enabled and added to the client. This is a good place to start background operations, make async calls, configure things before execution
375+
- `UpdateState`: Gets called on every event tracked by your client
376+
- `Unschedule`: Called when policy should stop running any scheduled flushes
377+
- `Reset`: Called after a flush is triggered (either by your policy, by another policy or manually)
378+
379+
They also have a `ShouldFlush` observable boolean value. When this is set to true the client will attempt to upload events. Each policy should reset this value to `false` according to its own logic, although it is pretty common to do it inside the `Reset` method.
380+
381+
```csharp
382+
class FlushOnScreenEventsPolicy : IFlushPolicy
383+
{
384+
private bool _screenEventsSeen = false;
385+
386+
public bool ShouldFlush() => _screenEventsSeen;
387+
388+
public void UpdateState(RawEvent @event)
389+
{
390+
// Only flush when at least a screen even happens
391+
if (@event is ScreenEvent)
392+
{
393+
_screenEventsSeen = true;
394+
}
395+
}
396+
397+
public void Reset()
398+
{
399+
_screenEventsSeen = false;
400+
}
401+
402+
public void Schedule(Analytics analytics) {}
403+
404+
public void Unschedule() {}
405+
}
406+
```
407+
408+
## Handling Errors
409+
You can handle analytics client errors through the `analyticsErrorHandler` option.
410+
411+
The error handler configuration requires an instance that implements `IAnalyticsErrorHandler` which will get called whenever an error happens on the analytics client. It will receive a general `Exception`, but you can check if the exception is a type of `AnalyticsError` and converts to get more info about the error. Checkout [here](https://github.com/segmentio/Analytics-CSharp/blob/main/Analytics-CSharp/Segment/Analytics/Errors.cs#L77) to see a full list of error types that analytics throws.
412+
413+
You can use this error handling to trigger different behaviours in the client when a problem occurs. For example if the client gets rate limited you could use the error handler to swap flush policies to be less aggressive:
414+
415+
```csharp
416+
class NetworkErrorHandler : IAnalyticsErrorHandler
417+
{
418+
private Analytics _analytics;
419+
420+
public NetworkErrorHandler(Analytics analytics)
421+
{
422+
_analytics = analytics;
423+
}
424+
425+
public void OnExceptionThrown(Exception e)
426+
{
427+
if (e is AnalyticsError error && error.ErrorType == AnalyticsErrorType.NetworkServerLimited)
428+
{
429+
_analytics.ClearFlushPolicies();
430+
// Add less persistent flush policies
431+
_analytics.AddFlushPolicy(new CountFlushPolicy(1000), new FrequencyFlushPolicy(60 * 60 * 1000));
432+
}
433+
}
434+
}
435+
```
436+
437+
### Reporting errors from plugins
438+
439+
Plugins can also report errors to the handler by using the [`.ReportInternalError`](https://github.com/segmentio/Analytics-CSharp/blob/main/Analytics-CSharp/Segment/Analytics/Errors.cs#L54) function of the analytics client, we recommend using the `AnalyticsErrorType.PluginError` for consistency, and attaching the `exception` with the actual exception that was hit:
440+
441+
```csharp
442+
try
443+
{
444+
// do something;
445+
}
446+
catch (Exception e)
447+
{
448+
this.Analytics.ReportInternalError(AnalyticsErrorType.PluginError, e, "Error from plugin");
449+
Analytics.Logger.Log(LogLevel.Error, e);
450+
}
451+
```
452+
453+
### Listen to Analytics Logs
454+
455+
Besides error handling, you could also provide a static `ISegmentLogger` to help log and debug as well as error handling. The same log that is reported by `ReportInternalError` is also reported to this static logger. The static logger also receives more errors and exceptions because it does not require an `Analytics` instance available. Thus, it's also a good idea to use the logger as an addition to `IAnalyticsErrorHandler`.
456+
```csharp
457+
Analytics.Logger = new SegmentLogger();
458+
459+
class SegmentLogger : ISegmentLogger
460+
{
461+
public void Log(LogLevel logLevel, Exception exception = null, string message = null)
462+
{
463+
switch (logLevel)
464+
{
465+
case LogLevel.Warning:
466+
case LogLevel.Information:
467+
case LogLevel.Debug:
468+
Console.Out.WriteLine("Message: " + message);
469+
break;
470+
case LogLevel.Critical:
471+
case LogLevel.Trace:
472+
case LogLevel.Error:
473+
Console.Error.WriteLine("Exception: " + exception?.StackTrace);
474+
Console.Error.WriteLine("Message: " + message);
475+
break;
476+
case LogLevel.None:
477+
default:
478+
break;
479+
}
480+
}
481+
}
482+
```
483+
484+
## Customize HTTP Client
485+
486+
The SDK allows you to have full control over the network components. You can easily swap out System.Net with your favorite network library by implementing `IHTTPClientProvider` and extending `HTTPClient`. Take a look at [this example](https://github.com/segmentio/Analytics-CSharp/blob/main/Samples/UnitySample/UnityHTTPClient.cs) where the default http client is fully replaced by Unity's `UnityWebRequest`.
487+
488+
### Proxying HTTP Calls
489+
490+
You can also redirect the HTTP calls to your own proxy server by implementing `IHTTPClientProvider` and extending `DefaultHTTPClient`:
491+
```csharp
492+
class ProxyHttpClient : DefaultHTTPClient
493+
{
494+
public ProxyHttpClient(string apiKey, string apiHost = null, string cdnHost = null) : base(apiKey, apiHost, cdnHost)
495+
{
496+
}
497+
498+
public override string SegmentURL(string host, string path)
499+
{
500+
if (host.Equals(_apiHost))
501+
{
502+
return "Your proxy api url";
503+
}
504+
else
505+
{
506+
return "Your proxy cdn url";
507+
}
508+
}
509+
}
510+
511+
class ProxyHttpClientProvider : IHTTPClientProvider
512+
{
513+
public HTTPClient CreateHTTPClient(string apiKey, string apiHost = null, string cdnHost = null)
514+
{
515+
return new ProxyHttpClient(apiKey, apiHost, cdnHost);
516+
}
517+
}
518+
```
519+
520+
## Customize Storage
521+
522+
The SDK also allows you to fully customize your storage strategy. It comes with two standard providers: `DefaultStorageProvider` that stores data to local disk and `InMemoryStorageProvider` that stores data all in memory. You can write up your own provider according to your needs, for example, store data to a database or to your own server directly, by implementing `IStorage` and `IStorageProvider`. Please refer to the implementation of [`Storage`](https://github.com/segmentio/Analytics-CSharp/blob/main/Analytics-CSharp/Segment/Analytics/Utilities/Storage.cs) as example.
523+
524+
## Json Library
525+
526+
The SDK supports `.netstandard 1.3` and `.netstandard 2.0` and auto assembles the internal Json library according to the target framework:
527+
* on `.netstandard 1.3`, the SDK uses Newtonsoft Json.NET
528+
* on `.netstandard 2.0`, the SDK uses System.Text.Json
529+
530+
531+
### Arrays
327532
To send an array as an event property, reference the [GitHub repo](https://github.com/segmentio/Serialization.NET/blob/main/Tests/JsonUtilityTest.cs#L24){:target="_blank"}. Below is an example of code you can implement to send an array of strings:
328533
329534
```c#
@@ -335,8 +540,30 @@ JsonObject customerJsonObj = new JsonObject
335540
};
336541
```
337542

543+
544+
## Samples
545+
546+
For sample usages of the SDK in specific platforms, checkout the following:
547+
548+
| Platform | Sample |
549+
|-------------|----------------------------------------------------------------------------------------------------------------------------------------|
550+
| Asp.Net | [Setup with dependency injection](https://github.com/segmentio/Analytics-CSharp/tree/main/Samples/AspNetSample) |
551+
| Asp.Net MVC | [Setup with dependency injection](https://github.com/segmentio/Analytics-CSharp/blob/main/Samples/AspNetMvcSample) |
552+
| Console | [Basic setups](https://github.com/segmentio/Analytics-CSharp/tree/main/Samples/ConsoleSample/Program.cs) |
553+
| Unity | [Singleton Analytics](https://github.com/segmentio/Analytics-CSharp/blob/main/Samples/UnitySample/SingletonAnalytics.cs) |
554+
| | [Lifecycle plugin](https://github.com/segmentio/Analytics-CSharp/blob/main/Samples/UnitySample/LifecyclePlugin.cs) |
555+
| | [Custom HTTPClient](https://github.com/segmentio/Analytics-CSharp/blob/main/Samples/UnitySample/UnityHTTPClient.cs) |
556+
| Xamarin | [Basic setups](https://github.com/segmentio/Analytics-CSharp/tree/main/Samples/XamarinSample) |
557+
| General | [Custom HTTP client](https://github.com/segmentio/Analytics-CSharp/tree/main/Samples/ConsoleSample/ProxyHttpClient.cs) |
558+
| | [Custom Storage](https://github.com/segmentio/Analytics-CSharp/blob/main/Analytics-CSharp/Segment/Analytics/Utilities/Storage.cs#L200) |
559+
| | [Flush Policy](https://github.com/segmentio/Analytics-CSharp/tree/main/Samples/ConsoleSample/FlushOnScreenEventsPolicy.cs) |
560+
| | [Custom Logger](https://github.com/segmentio/Analytics-CSharp/tree/main/Samples/ConsoleSample/SegmentLogger.cs) |
561+
| | [Custom Error Handler](https://github.com/segmentio/Analytics-CSharp/tree/main/Samples/ConsoleSample/NetworkErrorHandler.cs) |
562+
563+
564+
338565
## Compatibility
339-
This library targets `.NET Standard 2.0`. See the [list of compatible platforms](https://docs.microsoft.com/en-us/dotnet/standard/net-standard?tabs=net-standard-2-0){:target="_blank"}.
566+
This library targets `.NET Standard 1.3` and `.NET Standard 2.0`. See the [list of compatible platforms](https://www.nuget.org/packages/Segment.Analytics.CSharp/#supportedframeworks-body-tab){:target="_blank"}.
340567
341568
## Changelog
342569
[View the Analytics-CSharp changelog on GitHub](https://github.com/segmentio/analytics-csharp/releases){:target="_blank"}.

0 commit comments

Comments
 (0)