Skip to content

Commit 29b59f4

Browse files
authored
Merge pull request #87 from snowplow/feat/ai-claude
claude mds instrumentation
2 parents 407a2dd + ffc5223 commit 29b59f4

File tree

5 files changed

+1517
-0
lines changed

5 files changed

+1517
-0
lines changed

CLAUDE.md

Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
1+
# Snowplow Unity Tracker - Claude Code Documentation
2+
3+
## Project Overview
4+
The Snowplow Unity Tracker is a C# library for Unity that enables event tracking and analytics in Unity games and applications. It sends events to Snowplow collectors for data analysis, supporting multiple platforms including iOS, Android, Windows, Mac, Linux, and WebGL.
5+
6+
## Development Commands
7+
```bash
8+
# Build the tracker library
9+
cd SnowplowTracker && dotnet build
10+
11+
# Run tests (requires Unity 2021.3.12f1 LTS)
12+
# Open SnowplowTracker.Tests in Unity Editor
13+
# Window -> General -> Test Runner -> EditMode -> Run All
14+
15+
# Start test collector (requires Vagrant)
16+
vagrant up && vagrant ssh
17+
cd /vagrant && mb &
18+
curl -X POST -d @/vagrant/Resources/imposter.json http://localhost:2525/imposters
19+
20+
# Build demo game
21+
# Open SnowplowTracker.Demo in Unity Editor and build
22+
```
23+
24+
## Architecture
25+
The tracker follows a layered architecture with clear separation of concerns:
26+
27+
### Core Components
28+
- **Tracker**: Main entry point for event tracking operations
29+
- **Emitter**: Handles event transmission (AsyncEmitter, SyncEmitter, WebGlEmitter)
30+
- **Storage**: Event persistence using LiteDB or in-memory storage
31+
- **Events**: Strongly-typed event classes with builder pattern
32+
- **Payloads**: Event data structures and JSON serialization
33+
- **Subject**: User/device information management
34+
- **Session**: Session state and management
35+
36+
### Data Flow
37+
1. Application creates events using builder pattern
38+
2. Tracker validates and enriches events with context
39+
3. Events are queued in storage (LiteDB or memory)
40+
4. Emitter batches and sends events to collector
41+
5. Failed events are retried with backoff
42+
43+
## Core Architectural Principles
44+
45+
### 1. Builder Pattern for Events
46+
All events use fluent builder pattern for construction:
47+
```csharp
48+
// ✅ Correct: Use builder pattern
49+
var event = new PageView()
50+
.SetPageUrl("https://example.com")
51+
.SetCustomContext(contexts)
52+
.Build();
53+
```
54+
55+
### 2. Async-First Design
56+
Primary emitter is asynchronous with thread-safe operations:
57+
```csharp
58+
// ✅ Correct: Use AsyncEmitter for production
59+
IEmitter emitter = new AsyncEmitter(collectorUrl,
60+
HttpProtocol.HTTPS, HttpMethod.POST);
61+
```
62+
63+
### 3. Platform-Specific Adaptations
64+
Different implementations for different Unity platforms:
65+
```csharp
66+
// ✅ Correct: Platform-specific emitter selection
67+
IEmitter emitter = Application.platform == RuntimePlatform.WebGLPlayer
68+
? new WebGlEmitter(url)
69+
: new AsyncEmitter(url);
70+
```
71+
72+
### 4. Immutable Event Data
73+
Events are immutable once built to ensure thread safety:
74+
```csharp
75+
// ❌ Wrong: Modifying built event
76+
var event = new Structured().Build();
77+
event.category = "new"; // Compilation error
78+
79+
// ✅ Correct: Configure before building
80+
var event = new Structured()
81+
.SetCategory("category")
82+
.Build();
83+
```
84+
85+
## Layer Organization & Responsibilities
86+
87+
### SnowplowTracker/ (Core Library)
88+
- **Root**: Core tracker, subject, session, utilities
89+
- **Emitters/**: Event transmission strategies
90+
- **Events/**: Event type definitions and builders
91+
- **Payloads/**: Data structures and serialization
92+
- **Storage/**: Event persistence implementations
93+
- **Requests/**: HTTP request handling
94+
- **Enums/**: Type-safe enumerations
95+
96+
### SnowplowTracker.Tests/ (Unit Tests)
97+
- **Tests/**: NUnit test fixtures
98+
- **TestHelpers/**: Mock implementations and utilities
99+
100+
### SnowplowTracker.Demo/ (Example Unity Game)
101+
- **Scripts/**: Demo game implementation with tracker usage
102+
103+
## Critical Import Patterns
104+
105+
### Namespace Organization
106+
```csharp
107+
// ✅ Correct: Organized namespace imports
108+
using SnowplowTracker;
109+
using SnowplowTracker.Emitters;
110+
using SnowplowTracker.Events;
111+
using SnowplowTracker.Payloads.Contexts;
112+
using SnowplowTracker.Enums;
113+
```
114+
115+
### Unity-Specific Imports
116+
```csharp
117+
// ✅ Correct: Unity engine imports when needed
118+
using UnityEngine;
119+
using System.Collections;
120+
```
121+
122+
## Essential Library Patterns
123+
124+
### Tracker Initialization
125+
```csharp
126+
// ✅ Correct: Full initialization with session
127+
var emitter = new AsyncEmitter(collectorUrl);
128+
var subject = new Subject().SetUserId(userId);
129+
var session = new Session(null);
130+
var tracker = new Tracker(emitter, "namespace",
131+
"appId", subject, session);
132+
tracker.StartEventTracking();
133+
```
134+
135+
### Event Tracking
136+
```csharp
137+
// ✅ Correct: Track with contexts
138+
tracker.Track(new Structured()
139+
.SetCategory("game")
140+
.SetAction("click")
141+
.SetCustomContext(contexts)
142+
.Build());
143+
```
144+
145+
### Context Creation
146+
```csharp
147+
// ✅ Correct: Build contexts with fluent API
148+
var context = new MobileContext()
149+
.SetOsType("iOS")
150+
.SetOsVersion("14.0")
151+
.SetDeviceModel("iPhone 12")
152+
.Build();
153+
```
154+
155+
## Model Organization Pattern
156+
157+
### Event Hierarchy
158+
- **IEvent**: Base interface for all events
159+
- **AbstractEvent<T>**: Generic base with common fields
160+
- **Concrete Events**: PageView, Structured, Unstructured, etc.
161+
162+
### Payload Structure
163+
- **IPayload**: Base payload interface
164+
- **TrackerPayload**: Key-value event data
165+
- **SelfDescribingJson**: Schema-based JSON payloads
166+
167+
### Context Types
168+
- **IContext**: Base context interface
169+
- **AbstractContext**: Common context implementation
170+
- **Specific Contexts**: Mobile, Desktop, GeoLocation, Session
171+
172+
## Common Pitfalls & Solutions
173+
174+
### Storage on Mobile Platforms
175+
```csharp
176+
// ❌ Wrong: Using file storage on tvOS
177+
IStore store = new EventStore(); // Fails on tvOS
178+
179+
// ✅ Correct: Platform-appropriate storage
180+
IStore store = Application.platform == RuntimePlatform.tvOS
181+
? new InMemoryEventStore()
182+
: new EventStore();
183+
```
184+
185+
### Thread Safety in Emitters
186+
```csharp
187+
// ❌ Wrong: Direct collection manipulation
188+
emitter.eventQueue.Add(event); // Not thread-safe
189+
190+
// ✅ Correct: Use thread-safe Add method
191+
emitter.Add(payload); // Thread-safe
192+
```
193+
194+
### Base64 Encoding for Custom Events
195+
```csharp
196+
// ❌ Wrong: Forgetting base64 encoding
197+
var tracker = new Tracker(emitter, ns, appId,
198+
base64Encoded: false); // May cause issues
199+
200+
// ✅ Correct: Enable base64 for compatibility
201+
var tracker = new Tracker(emitter, ns, appId,
202+
base64Encoded: true); // Default and recommended
203+
```
204+
205+
### Unity Lifecycle Management
206+
```csharp
207+
// ❌ Wrong: Not stopping tracker
208+
void OnApplicationPause(bool pause) { }
209+
210+
// ✅ Correct: Manage tracker lifecycle
211+
void OnApplicationPause(bool pause) {
212+
if (pause) tracker.StopEventTracking();
213+
else tracker.StartEventTracking();
214+
}
215+
```
216+
217+
## File Structure Template
218+
```
219+
snowplow-unity-tracker/
220+
├── SnowplowTracker/ # Core library project
221+
│ └── SnowplowTracker/
222+
│ ├── Emitters/ # Event transmission
223+
│ ├── Events/ # Event types
224+
│ ├── Payloads/ # Data structures
225+
│ │ └── Contexts/ # Context types
226+
│ ├── Storage/ # Persistence layer
227+
│ ├── Requests/ # HTTP handling
228+
│ ├── Enums/ # Type enumerations
229+
│ ├── Tracker.cs # Main tracker class
230+
│ ├── Subject.cs # User/device info
231+
│ └── Session.cs # Session management
232+
├── SnowplowTracker.Tests/ # Unit test project
233+
│ └── Assets/Tests/ # NUnit test fixtures
234+
└── SnowplowTracker.Demo/ # Demo Unity game
235+
└── Assets/Scripts/ # Example implementation
236+
```
237+
238+
## Quick Reference
239+
240+
### Import Checklist
241+
- [ ] `using SnowplowTracker;` - Core namespace
242+
- [ ] `using SnowplowTracker.Emitters;` - For emitter types
243+
- [ ] `using SnowplowTracker.Events;` - For event builders
244+
- [ ] `using SnowplowTracker.Payloads.Contexts;` - For contexts
245+
- [ ] `using SnowplowTracker.Enums;` - For enumerations
246+
247+
### Common Event Types
248+
- **PageView**: Web page views in WebGL builds
249+
- **ScreenView**: Mobile screen transitions
250+
- **Structured**: Custom categorized events
251+
- **Unstructured**: Schema-based custom events
252+
- **Timing**: Performance measurements
253+
- **EcommerceTransaction**: Purchase events
254+
255+
### Platform Considerations
256+
- **iOS/Android**: Use AsyncEmitter with EventStore
257+
- **WebGL**: Use WebGlEmitter for browser compatibility
258+
- **tvOS**: Use InMemoryEventStore (no file system)
259+
- **Desktop**: Full feature support with all emitters
260+
261+
### Testing Patterns
262+
- Use `BaseEmitter` for mocking in tests
263+
- Test with local Mountebank collector
264+
- Verify event payloads with `GetLastEvent()`
265+
- Check thread safety with concurrent operations
266+
267+
## Contributing to CLAUDE.md
268+
269+
When adding or updating content in this document, please follow these guidelines:
270+
271+
### File Size Limit
272+
- **CLAUDE.md must not exceed 40KB** (currently ~19KB)
273+
- Check file size after updates: `wc -c CLAUDE.md`
274+
- Remove outdated content if approaching the limit
275+
276+
### Code Examples
277+
- Keep all code examples **4 lines or fewer**
278+
- Focus on the essential pattern, not complete implementations
279+
- Use `// ❌` and `// ✅` to clearly show wrong vs right approaches
280+
281+
### Content Organization
282+
- Add new patterns to existing sections when possible
283+
- Create new sections sparingly to maintain structure
284+
- Update the architectural principles section for major changes
285+
- Ensure examples follow current codebase conventions
286+
287+
### Quality Standards
288+
- Test any new patterns in actual code before documenting
289+
- Verify imports and syntax are correct for the codebase
290+
- Keep language concise and actionable
291+
- Focus on "what" and "how", minimize "why" explanations
292+
293+
### Multiple CLAUDE.md Files
294+
- **Directory-specific CLAUDE.md files** can be created for specialized modules
295+
- Follow the same structure and guidelines as this root CLAUDE.md
296+
- Keep them focused on directory-specific patterns and conventions
297+
- Maximum 20KB per directory-specific CLAUDE.md file
298+
299+
### Instructions for LLMs
300+
When editing files in this repository, **always check for CLAUDE.md guidance**:
301+
302+
1. **Look for CLAUDE.md in the same directory** as the file being edited
303+
2. **If not found, check parent directories** recursively up to project root
304+
3. **Follow the patterns and conventions** described in the applicable CLAUDE.md
305+
4. **Prioritize directory-specific guidance** over root-level guidance when conflicts exist

0 commit comments

Comments
 (0)