Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
298 changes: 298 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,298 @@
# GitHub Copilot Instructions for Application Insights JavaScript SDK

## Project Overview
This is the **Microsoft Application Insights JavaScript SDK** - a browser-based telemetry library for monitoring web applications. The SDK tracks page views, user interactions, performance metrics, exceptions, and custom events.

## Architecture & Structure

### Monorepo Structure
- **AISKU/**: Main Application Insights SDK package
- **AISKULight/**: Lightweight version of the SDK
- **shared/**: Core shared libraries (AppInsightsCore, AppInsightsCommon, 1ds-core-js)
- **extensions/**: Plugin-based extensions (analytics, dependencies, etc.)
- **channels/**: Data transmission channels (online, offline, tee)
- **tools/**: Build and development tools
- **examples/**: Sample implementations

### Key Technologies
- **TypeScript/JavaScript**: Primary languages (ES5 target for browser compatibility)
- **Rush**: Monorepo management tool
- **Rollup**: Module bundler
- **Grunt**: Task runner
- **Dynamic Proto**: Dynamic prototype pattern for performance

## Code Style & Patterns

### TypeScript/JavaScript Conventions
- Use **ES5-compatible** syntax for browser support and target ES5 for modern browsers
- Prefer `function` declarations over arrow functions for better IE compatibility
- Use `var` instead of `let/const` in JavaScript files for ES5 compatibility (use `let/const` in TypeScript files)
- Always use semicolons
- Use 4-space indentation
- Maximum line length: 140 characters

### Naming Conventions
- **Classes**: PascalCase (e.g., `PageViewManager`, `TelemetryContext`)
- **Interfaces**: PascalCase with `I` prefix (e.g., `ITelemetryItem`, `IPageViewTelemetry`)
- **Methods/Functions**: camelCase (e.g., `trackPageView`, `sendTelemetry`)
- **Constants**: UPPER_SNAKE_CASE (e.g., `MAX_DURATION_ALLOWED`)
- **Private variables**: underscore prefix (e.g., `_logger`, `_hasInitialized`)
- **Enums**: PascalCase with `e` prefix (e.g., `eLoggingSeverity`, `eInternalMessageId`)
- Must be const enums with integer values (not strings)
- Use `createEnumStyle` helper for exported enums
- All usage should reference the const enum directly

### Dynamic Proto Pattern
This project uses a unique `dynamicProto` pattern for performance optimization. This pattern should be used for all classes:

```typescript
export class MyClass {
constructor() {
dynamicProto(MyClass, this, (_self, _base) => {
// Private variables should be included inside the constructor closure
// They are not publicly visible on the class
let _logger = _self._logger;
let _hasInitialized = false;

// Public methods need @DynamicProtoStub comment for TypeScript definitions
_self.myMethod = () => {
// Method implementation
};
});
}

/**
* @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
*/
public myMethod(): void {
// This stub will be replaced by the dynamicProto implementation
}
}
```

Key requirements:
- Use this pattern for all classes
- Private variables must be inside the constructor closure
- Public functions need `@DynamicProtoStub` comment for TypeScript definition generation
- Never add implementation code to the stub methods

### Error Handling
- Use `_throwInternal` for logging diagnostic errors
- Always include telemetry context in error messages
- Use appropriate logging severity levels: `CRITICAL`, `WARNING`, `INFORMATION`

```typescript
_throwInternal(_logger,
eLoggingSeverity.WARNING,
_eInternalMessageId.InvalidDurationValue,
"Invalid page load duration value",
{ total, network, request, response, dom });
```

### Performance Considerations
- Minimize object allocations in hot paths
- Use `doPerf()` wrapper for performance tracking
- Avoid synchronous operations that could block the browser
- Implement lazy initialization where possible
- Use object pooling for frequently created objects
- Minimize the size of generated JavaScript by avoiding certain TypeScript features:
- Do not use the spread `...` operator
- Do not use optional chaining `?.` operator
- Do not use the nullish coalescing `??` operator - use `||` instead
- These restrictions will be removed once ES5 support is discontinued

## Browser Compatibility

### Target Support
- **Modern browsers**: Chrome, Firefox, Safari, Edge (targeting ES5 for modern browsers)
- **Legacy support**: Internet Explorer 8+ (ES5 compatibility required)
- **Mobile browsers**: iOS Safari, Android Chrome
- **Non-browser runtimes**: Node.js and other browser-like environments (for worker contexts and server-side rendering)

### Compatibility Patterns
- Feature detection over browser detection
- Graceful degradation for missing APIs
- Use existing polyfills rather than creating new ones
- Safe API usage with null checks

### Async Operations Support
Support async operations using ts-async helpers instead of native async/await:
- Use `doAwait` for `await` operations
- Use `doAwaitResponse` to handle catch operations for asynchronous operations
- Use `createPromise`, `createSyncPromise`, `createIdlePromise` instead of declaring functions as `async`
- Return type should use `IPromise` instead of `Promise` for IE support

```typescript
const perf = getPerformance();
if (perf && perf.timing && perf.timing.navigationStart) {
// Use performance API
}
```

## Telemetry & Data Collection

### Core Telemetry Types
- **Page Views**: `IPageViewTelemetry` - Track page navigation
- **Events**: `IEventTelemetry` - Custom user actions
- **Metrics**: `IMetricTelemetry` - Numeric measurements
- **Exceptions**: `IExceptionTelemetry` - Error tracking
- **Dependencies**: `IDependencyTelemetry` - External calls
- **Traces**: `ITraceTelemetry` - Logging messages

### Data Privacy & Compliance
- Never collect PII (personally identifiable information) by default
- Sanitize URLs and remove sensitive query parameters
- Implement data sampling and throttling
- Support opt-out mechanisms
- Follow GDPR/privacy regulations

### Performance Monitoring
- Use `IPerfManager` and `IPerfEvent` for internal performance tracking
- Collect browser timing APIs (Navigation Timing, Resource Timing)
- Track page load performance metrics
- Monitor SDK overhead and impact

## Plugin Architecture

### Plugin Development
- Extend `BaseTelemetryPlugin` for new plugins
- Implement `ITelemetryPlugin` interface
- Use `IProcessTelemetryContext` for processing pipeline
- Support plugin chaining and dependencies

```typescript
export class MyPlugin extends BaseTelemetryPlugin {
public processTelemetry(evt: ITelemetryItem, itemCtx?: IProcessTelemetryContext) {
// Process telemetry
this.processNext(evt, itemCtx);
}
}
```

### Extension Points
- **Telemetry Initializers**: Modify telemetry before sending
- **Dependency Listeners**: Track AJAX/fetch calls
- **Channels**: Custom data transmission

## Testing Patterns

### Unit Testing
- Use framework-agnostic test patterns
- Mock browser APIs consistently
- Test both success and failure scenarios
- Verify telemetry data structure and content

### Browser Testing
- Cross-browser compatibility testing
- Performance regression testing
- Memory leak detection
- Network failure scenarios

### Test Organization
- Collocate tests with source code in `Tests/` directories
- Use descriptive test names
- Group related tests in test suites
- Mock external dependencies

## Configuration & Initialization

### SDK Configuration
- Support both snippet and npm installation
- Provide sensible defaults
- Allow runtime configuration changes
- Validate configuration parameters
- Configuration names should be descriptive but mindful of browser bundle size by keeping names concise and readable

```typescript
const config: IConfiguration = {
instrumentationKey: "your-key",
enableAutoRouteTracking: true,
disableTelemetry: false,
samplingPercentage: 100
};
```

### Initialization Patterns
- Lazy initialization to minimize startup impact
- Graceful handling of initialization failures
- Support for multiple SDK instances
- Plugin dependency resolution

## Performance Guidelines

### Bundle Size Optimization
- Tree-shaking friendly exports
- Conditional feature loading
- Minimize third-party dependencies
- Use rollup for optimal bundling

### Runtime Performance
- Avoid blocking the main thread
- Use requestIdleCallback when available
- Batch telemetry operations
- Implement efficient queuing mechanisms

### Memory Management
- Clean up event listeners on teardown
- Avoid memory leaks in long-running applications
- Use weak references where appropriate
- Implement proper disposal patterns

### Code Organization & Tree-Shaking
- Each package should be side-effect free to enable proper tree-shaking
- All code should be tree-shakable - avoid global side effects
- Use lazy initialization for any globals via `ILazyValue` interface or similar patterns
- Distinguish between "value not yet checked/assigned" vs "resulting value is null/undefined"
- Export functions and classes individually rather than as default exports
- Avoid executing code at module load time

## Common Patterns & Anti-Patterns

### ✅ Good Practices
- Use TypeScript interfaces for contracts
- Implement proper error boundaries
- Follow the plugin architecture
- Use performance monitoring internally
- Sanitize all user inputs
- Support both sync and async operations

### ❌ Anti-Patterns
- Don't block the browser UI thread
- Avoid throwing unhandled exceptions
- Don't collect sensitive user data
- Avoid tight coupling between components
- Don't ignore browser compatibility
- Avoid memory leaks in event handlers

## Documentation Standards

### Code Comments
- Use TypeDoc format for public APIs
- Document complex algorithms and business logic
- Include examples for public methods
- Explain browser compatibility considerations

### Interface Documentation
- Document all public interfaces thoroughly using TypeDoc comments
- Include parameter validation requirements
- Include defaults and any relevant examples
- Specify return value contracts
- Note any side effects or state changes

## Build & Deployment

### Build Process
- Rush for monorepo management
- TypeScript compilation with strict settings
- Rollup bundling with multiple output formats
- Minification and size optimization

### Release Process
- Semantic versioning
- Automated testing before release
- Bundle size monitoring
- Browser compatibility verification

---

*This document helps GitHub Copilot understand the unique patterns, architecture, and requirements of the Application Insights JavaScript SDK project.*
2 changes: 1 addition & 1 deletion .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ on:
# The branches below must be a subset of the branches above
branches: [ "main", "master", "beta", "Release*", "release*", "*-legacy", "legacy-v1" ]
schedule:
- cron: '15 */2 * * *' # run every 2 hours at 15 minutes past the hour
- cron: '15 17 * * 2' # Every Tuesday at 17:15 UTC

jobs:
analyze:
Expand Down
1 change: 1 addition & 0 deletions AISKU/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ See [Breaking Changes](https://microsoft.github.io/ApplicationInsights-JS/upgrad
| Version | Full Size | Raw Minified | GZip Size
|---------|-----------|--------------|-------------
| [<nightly3>](https://github.com/microsoft/ApplicationInsights-JS/tree/main/AISKU) | [![full size size](https://js.monitor.azure.com/nightly/ai.3-nightly3.js.svg)](https://js.monitor.azure.com/nightly/ai.3-nightly3.js.svg)| ![minified size size](https://js.monitor.azure.com/nightly/ai.3-nightly3.min.js.svg) | ![gzip size](https://js.monitor.azure.com/nightly/ai.3-nightly3.min.js.gzip.svg)
| 3.3.9: | [![full size size](https://js.monitor.azure.com/scripts/b/ai.3.3.9.js.svg)](https://js.monitor.azure.com/scripts/b/ai.3.3.9.js.svg)| ![minified size size](https://js.monitor.azure.com/scripts/b/ai.3.3.9.min.js.svg) | ![gzip size](https://js.monitor.azure.com/scripts/b/ai.3.3.9.min.js.gzip.svg)
| 3.3.8: | [![full size size](https://js.monitor.azure.com/scripts/b/ai.3.3.8.js.svg)](https://js.monitor.azure.com/scripts/b/ai.3.3.8.js.svg)| ![minified size size](https://js.monitor.azure.com/scripts/b/ai.3.3.8.min.js.svg) | ![gzip size](https://js.monitor.azure.com/scripts/b/ai.3.3.8.min.js.gzip.svg)
| 3.3.7: | [![full size size](https://js.monitor.azure.com/scripts/b/ai.3.3.7.js.svg)](https://js.monitor.azure.com/scripts/b/ai.3.3.7.js.svg)| ![minified size size](https://js.monitor.azure.com/scripts/b/ai.3.3.7.min.js.svg) | ![gzip size](https://js.monitor.azure.com/scripts/b/ai.3.3.7.min.js.gzip.svg)
| 3.3.6: | [![full size size](https://js.monitor.azure.com/scripts/b/ai.3.3.6.js.svg)](https://js.monitor.azure.com/scripts/b/ai.3.3.6.js.svg)| ![minified size size](https://js.monitor.azure.com/scripts/b/ai.3.3.6.min.js.svg) | ![gzip size](https://js.monitor.azure.com/scripts/b/ai.3.3.6.min.js.gzip.svg)
Expand Down
2 changes: 1 addition & 1 deletion AISKU/Tests/Perf/src/AISKUPerf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export class AppInsightsInitPerfTestClass {
* should update version after new release
* version with doperf(): after 2.5.6
* */
var defaultVer = "3.3.8";
var defaultVer = "3.3.9";
this.version = ver? ver:this._getQueryParameterVersion(defaultVer);
this.perfEventsBuffer = [];
this.perfEventWaitBuffer = [];
Expand Down
2 changes: 1 addition & 1 deletion AISKU/Tests/Unit/src/AISKUSize.Tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export class AISKUSizeCheck extends AITestClass {
private readonly MAX_BUNDLE_DEFLATE_SIZE = 59;
private readonly rawFilePath = "../dist/es5/applicationinsights-web.min.js";
// Automatically updated by version scripts
private readonly currentVer = "3.3.8";
private readonly currentVer = "3.3.9";
private readonly prodFilePath = `../browser/es5/ai.${this.currentVer[0]}.min.js`;

public testInitialize() {
Expand Down
2 changes: 1 addition & 1 deletion AISKU/Tests/Unit/src/CdnPackaging.tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const enum CdnFormat {

export class CdnPackagingChecks extends AITestClass {
// Automatically updated by version scripts
private readonly currentVer = "3.3.8";
private readonly currentVer = "3.3.9";

public testInitialize() {
}
Expand Down
Loading