A practical guide for getting started with TraceFlow-IEF and the Log Analyzer feature.
- Installation
- Running the Application
- Log Analyzer Setup
- Common Tasks
- Debugging Tips
- Code Examples
- Testing
- Node.js: 18.x or later
- npm: 9.x or later
- Browser: Chrome 90+, Firefox 90+, Safari 15+, or Edge 90+
# Clone the repository
git clone https://github.com/your-org/TraceFlow-IEF.git
cd TraceFlow-IEF
# Navigate to client folder
cd client
# Install dependencies
npm install# Start the development server with hot reload
npm run devThe application will be available at http://localhost:3000.
# Create optimized production build
npm run build
# Preview the production build locally
npm run preview| Command | Description |
|---|---|
npm run lint |
Run ESLint on the codebase |
npm run test |
Run unit tests with Vitest |
-
Application Insights Access
- Application ID (GUID) from Azure Portal
- API Key with read permissions
- Logs must include Journey Recorder events
-
Enable Journey Recorder in B2C Policy
<UserJourneyBehaviors> <JourneyInsights TelemetryEngine="ApplicationInsights" InstrumentationKey="your-key" DeveloperMode="true" ClientEnabled="true" ServerEnabled="true" TelemetryVersion="1.0.0" /> </UserJourneyBehaviors>
- Navigate to the Log Analyzer page
- Enter your Application Insights credentials
- Set timespan (e.g.,
PT24Hfor last 24 hours) - Click "Fetch Logs"
- Select a flow from the results
Use the search field to find specific logs:
// Search filters work on the message content
// Examples:
"user@email.com" // Find logs containing email
"AAD-UserWriteUsing" // Find specific TP executions
"error" // Find error messages
"CorrelationId-123" // Find specific correlationLogs are automatically grouped by PolicyId. The flow selector shows:
- Policy name
- Start/end time
- Step count
- Completion status
- Error indicators
Each trace step shows:
| Field | Description |
|---|---|
| Step # | Orchestration step number |
| Handler | B2C handler that executed |
| Technical Profiles | TPs involved in this step |
| Result | Success, Error, or Skipped |
| Duration | Time until next step |
The statebag inspector shows:
- Current claims (
Complex-CLMS) - Orchestration state (
ORCH_CS,ORCH_TE) - Session data (
SSO_PP) - Error details
- Look for red indicators in the flow list
- Check trace steps with "Error" result
- Inspect FatalException clips in detail view
- Search for "Exception" in raw logs
- Select a flow
- Step through the trace
- Watch
claimsSnapshotin each step - Compare before/after values
- Check
durationfield on each step - Look for long-running REST API calls
- Identify slow claims transformations
- Check for excessive validation TP calls
| Symptom | Likely Cause | Solution |
|---|---|---|
| No logs appear | Wrong timespan | Extend timespan |
| Partial flows | Log truncation | Already handled by aggregation |
| Missing steps | Filter excluding events | Check Event type filters |
| Empty trace | No AUTH events | Check Journey Recorder config |
import { useLogStore } from "@/stores/log-store";
function MyComponent() {
const { logs, selectedLog, traceSteps, isLoading } = useLogStore();
// Access current log
console.log(selectedLog?.correlationId);
// Access trace steps
traceSteps.forEach(step => {
console.log(`Step ${step.stepOrder}: ${step.actionHandler}`);
});
}import { useLogStore } from "@/stores/log-store";
function fetchLogs() {
const store = useLogStore.getState();
store.fetchLogs({
applicationId: "your-app-id",
apiKey: "your-api-key",
maxRows: 100,
timespan: "PT24H"
});
}import { isHandlerResultClip, isHeadersClip } from "@/types/journey-recorder";
function analyzeLog(log: LogRecord) {
for (const clip of log.clips) {
if (isHeadersClip(clip)) {
console.log("Policy:", clip.Content.PolicyId);
console.log("Event:", clip.Content.EventInstance);
}
if (isHandlerResultClip(clip)) {
console.log("Result:", clip.Content.Result);
if (clip.Content.Exception) {
console.error("Error:", clip.Content.Exception.Message);
}
}
}
}import { parseTrace, logsToTraceInput } from "@/lib/trace";
function customAnalysis(logs: LogRecord[]) {
const input = logsToTraceInput(logs);
const result = parseTrace(input);
// Analyze trace steps
result.traceSteps.forEach(step => {
if (step.result === "Error") {
console.error(`Error at step ${step.stepOrder}:`, step.errorMessage);
}
// Check for specific TPs
if (step.technicalProfiles.includes("AAD-UserReadUsingObjectId")) {
console.log("User read at step", step.stepOrder);
}
});
// Access final state
console.log("Final claims:", result.finalClaims);
console.log("Final statebag:", result.finalStatebag);
}import { describe, it, expect } from "vitest";
import { parseTrace } from "@/lib/trace";
describe("My Feature", () => {
it("should handle specific scenario", () => {
const logs = [
{
id: "log-1",
timestamp: new Date("2024-01-01T10:00:00Z"),
policyId: "B2C_1A_Test",
correlationId: "test-123",
clips: [
{ Kind: "Headers", Content: { EventInstance: "Event:AUTH", PolicyId: "B2C_1A_Test", CorrelationId: "test-123", TenantId: "test", UserJourneyRecorderEndpoint: "test" } },
{ Kind: "Action", Content: "ProcessOrchestrationStep" },
{ Kind: "HandlerResult", Content: { Result: true, Statebag: { "ORCH_CS": { c: "Int32", k: "ORCH_CS", v: "1", p: 0 } } } }
]
}
];
const result = parseTrace(logs);
expect(result.success).toBe(true);
expect(result.traceSteps).toHaveLength(1);
expect(result.traceSteps[0].stepOrder).toBe(1);
});
});import { describe, it, expect, beforeEach } from "vitest";
import { useLogStore } from "@/stores/log-store";
describe("Log Store Integration", () => {
beforeEach(() => {
useLogStore.getState().reset();
});
it("should process logs and generate trace", () => {
const store = useLogStore.getState();
// Simulate setting logs
store.setLogs(mockLogs);
store.generateTrace();
const state = useLogStore.getState();
expect(state.traceSteps.length).toBeGreaterThan(0);
});
});// Create reusable test fixtures
function createTestLog(overrides: Partial<LogRecord> = {}): LogRecord {
return {
id: "test-log-1",
timestamp: new Date(),
policyId: "B2C_1A_Test",
correlationId: "test-correlation",
cloudRoleInstance: "test-instance",
rawIds: ["test-log-1"],
payloadText: "[]",
parsedPayload: [],
clips: [],
customDimensions: {
correlationId: "test-correlation",
eventName: "",
tenant: "test",
userJourney: "B2C_1A_Test",
version: "1.0"
},
...overrides
};
}
function createOrchestrationClips(step: number): Clip[] {
return [
{
Kind: "Headers",
Content: {
EventInstance: "Event:AUTH",
PolicyId: "B2C_1A_Test",
CorrelationId: "test",
TenantId: "test",
UserJourneyRecorderEndpoint: "test"
}
},
{ Kind: "Action", Content: "ProcessOrchestrationStep" },
{
Kind: "HandlerResult",
Content: {
Result: true,
Statebag: {
"ORCH_CS": { c: "Int32", k: "ORCH_CS", v: String(step), p: 0 }
}
}
}
];
}| File | Purpose |
|---|---|
src/lib/api/application-insights-client.ts |
API client |
src/lib/app-insights-processor.ts |
Log processing |
src/stores/log-store.ts |
State management |
src/lib/trace/trace-parser.ts |
Trace parsing |
src/lib/trace/interpreters/*.ts |
Handler interpreters |
src/lib/trace/services/flow-analyzer.ts |
Flow grouping |
src/components/policy-logs/*.tsx |
UI components |
src/types/logs.ts |
Log types |
src/types/journey-recorder.ts |
Clip types |
src/types/trace.ts |
Trace types |
- LOGGING_ARCHITECTURE.md - Full architecture docs
- TRACE_INTERPRETERS.md - Interpreter reference
- CLIP_REFERENCE.md - Clip type reference