@@ -14,12 +14,14 @@ This library is one of Segment’s most popular Flagship libraries. It is active
14
14
- [ Plugin Architecture] ( #plugin-architecture )
15
15
- [ Adding a plugin] ( #adding-a-plugin )
16
16
- [ Utility Methods] ( #utility-methods )
17
+ - [ Enrichment Closure] ( #enrichment-closure )
17
18
- [ Controlling Upload With Flush Policies] ( #controlling-upload-with-flush-policies )
18
19
- [ Handling Errors] ( #handling-errors )
19
20
- [ Customize HTTP Client] ( #customize-http-client )
20
21
- [ Customize Storage] ( #customize-storage )
21
22
- [ Json Library] ( #json-library )
22
23
- [ Samples] ( #samples )
24
+ - [ FAQs] ( #faqs )
23
25
- [ Compatibility] ( #compatibility )
24
26
- [ Changelog] ( #changelog )
25
27
- [ Contributing] ( #contributing )
@@ -90,6 +92,7 @@ To get started with the Analytics-CSharp library:
90
92
| `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 ` |
91
93
| `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. |
92
94
| `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`. |
95
+ | `eventPipelineProvider` | The default is `EventPipelineProvider`. <br>This sets a custom event pipeline to define how Analytics handles events. The default `EventPipelineProvider` processes events asynchronously. Use `SyncEventPipelineProvider` to make manual flush operations synchronous. |
93
96
94
97
## Tracking Methods
95
98
@@ -361,6 +364,22 @@ The `reset` method clears the SDK’s internal stores for the current user and g
361
364
analytics .Reset ()
362
365
```
363
366
367
+ ## Enrichment Closure
368
+ To modify the properties of an event , you can either write an enrichment plugin that applies changes to all events , or pass an enrichment closure to the analytics call to apply changes to a specific event .
369
+
370
+ ```c #
371
+ analytics .Track (" MyEvent" , properties , @event =>
372
+ {
373
+ if (@event is TrackEvent trackEvent )
374
+ {
375
+ // update properties of this event
376
+ trackEvent .UserId = " foo" ;
377
+ }
378
+
379
+ return @event ;
380
+ });
381
+ ```
382
+
364
383
## Controlling Upload With Flush Policies
365
384
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 .**
366
385
@@ -584,6 +603,92 @@ For sample usages of the SDK in specific platforms, checkout the following:
584
603
| | [Custom Logger ](https :// github.com/segmentio/Analytics-CSharp/tree/main/Samples/ConsoleSample/SegmentLogger.cs) |
585
604
| | [Custom Error Handler ](https :// github.com/segmentio/Analytics-CSharp/tree/main/Samples/ConsoleSample/NetworkErrorHandler.cs) |
586
605
606
+ ## FAQs
607
+
608
+ ### Should I make Analytics a singleton or scoped in .NET?
609
+
610
+ The SDK supports both , but be aware of the implications of choosing one over the other :
611
+
612
+ | Feature | Singleton | Scoped |
613
+ | -- | -- | -- |
614
+ | ** Fetch Settings ** | Settings are fetched only once at application startup . | Settings are fetched on every request . |
615
+ | ** Flush ** | Supports both async and sync flush . | Requires sync flush . Should flush per event or on page redirect / close to avoid data loss . |
616
+ | ** Internal State ** | The internal state (`userId `, `anonId `, etc .) is shared across sessions and cannot be used . (* This is an overhead we are working to minimize *.) | The internal state is safe to use since a new instance is created per request . |
617
+ | ** UserId for Events ** | Requires adding `UserIdPlugin ` and calling analytics APIs with `userId ` to associate the correct `userId ` with events . | No need for `UserIdPlugin ` or passing `userId ` in API calls . Instead , call `analytics .Identify ()` to update the internal state with the `userId `. Successive events are auto - stamped with that `userId `. |
618
+ | ** Storage ** | Supports both local storage and in - memory storage . | Requires in - memory storage . (* Support for local storage is in progress *.) |
619
+
620
+
621
+ In a nutshell , to register Analytics as singleton :
622
+
623
+ ```c #
624
+ var configuration = new Configuration (
625
+ writeKey : " YOUR_WRITE_KEY" ,
626
+ // Use in-memory storage to keep the SDK stateless.
627
+ // The default storage also works if you want to persist events.
628
+ storageProvider : new InMemoryStorageProvider (),
629
+ // Use a synchronous pipeline to make manual flush operations synchronized.
630
+ eventPipelineProvider : new SyncEventPipelineProvider ()
631
+ );
632
+
633
+ var analytics = new Analytics (configuration );
634
+
635
+ // Add UserIdPlugin to associate events with the provided userId.
636
+ analytics .Add (new UserIdPlugin ());
637
+
638
+ // Call analytics APIs with a userId. The UserIdPlugin will update the event with the provided userId.
639
+ analytics .Track (" user123" , " foo" , properties );
640
+
641
+ // This is a blocking call due to SyncEventPipelineProvider.
642
+ // Use the default EventPipelineProvider for asynchronous flush.
643
+ analytics .Flush ();
644
+
645
+ // Register Analytics as a singleton.
646
+ ```
647
+
648
+ To register Analytics as scoped :
649
+
650
+ ```c #
651
+ var configuration = new Configuration (
652
+ writeKey : " YOUR_WRITE_KEY" ,
653
+ // Requires in-memory storage.
654
+ storageProvider : new InMemoryStorageProvider (),
655
+ // Flush per event to prevent data loss in case of a page close.
656
+ // Alternatively, manually flush on page close.
657
+ flushAt : 1 ,
658
+ // Requires a synchronous flush.
659
+ eventPipelineProvider : new SyncEventPipelineProvider ()
660
+ );
661
+
662
+ var analytics = new Analytics (configuration );
663
+
664
+ // Update the internal state with a userId.
665
+ analytics .Identify (" user123" );
666
+
667
+ // Subsequent events are auto-stamped with the userId from the internal state.
668
+ analytics .Track (" foo" , properties );
669
+
670
+ // This is a blocking call due to SyncEventPipelineProvider.
671
+ analytics .Flush ();
672
+
673
+ // Register Analytics as scoped.
674
+ ```
675
+
676
+ ### Which JSON library does this SDK use?
677
+
678
+ The SDK supports `.netstandard 1 . 3 ` and `.netstandard 2 . 0 ` and automatically selects the internal JSON library based on the target framework :
679
+
680
+ * In `.netstandard 1 . 3 `, the SDK uses `Newtonsoft Json .NET `
681
+ * In `.netstandard 2 . 0 `, the SDK uses `System .Text .Json `
682
+
683
+ Be ware that both Analytics .NET and Analytics .Xamarin use `Newtonsoft Json .NET `. If you encounter issues where JSON dictionary values are turned into empty arrays , it is likely that :
684
+
685
+ 1 . You are targeting `.netstandard 2 . 0 `.
686
+ 2 . Your properties use `Newtonsoft Json .NET ` objects or arrays .
687
+
688
+ To resolve this , you can :
689
+ * Option 1 : Target `.netstandard 1 . 3 `
690
+ * Option 2 : Upgrade your JSON library to `System .Text .Json `
691
+
587
692
## Compatibility
588
693
This library targets `.NET Standard 1 . 3 ` and `.NET Standard 2 . 0 `. Checkout [here ](https :// www.nuget.org/packages/Segment.Analytics.CSharp/#supportedframeworks-body-tab) for compatible platforms.
589
694
0 commit comments