implementing-telemetry
Skill1 starsChanged 9 months agoMITView on GitHub
Logs custom events to Application Insights using Feature Telemetry or Session.LogMessage, tracks feature adoption with LogUptake, and queries telemetry data with KQL. Use when instrumenting BC extensions, debugging production issues, monitoring API integrations, or tracking feature usage.
In this repository12 other files it gives its agents.
- AGENTS.mdAGENTS.md
- authenticating-with-oauthSkill
- binding-event-subscribersSkill
- building-cue-rolecentersSkill
- consuming-bc-standard-apiSkill
- controlling-al-accessSkill
- creating-bc-custom-apiSkill
- handling-bc-filesSkill
- implementing-al-interfacesSkill
- integrating-azure-servicesSkill
- optimizing-bc-performanceSkill
- writing-git-commitsSkill
The file
We split this skill into the rules it gives an agent
1 rule. About 0 are common, 0 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 161
DataClassification: ALWAYS use SystemMetadata - other values won't be sent!
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Skill: AL Telemetry Implementation
Validation Gates
- After Step 3: Telemetry Logger registered (check
OnRegisterTelemetryLoggerfires) - After Step 5: Events appear in Application Insights within 5 minutes
- Final: KQL query returns your custom eventIds with correct dimensions
Key Concept
EventId prefix: Platform adds AL automatically → Code: APP-0001 → App Insights: ALAPP-0001
Procedure
Step 1: Configure Application Insights
In app.json:
{
"applicationInsightsConnectionString": "InstrumentationKey=xxx;IngestionEndpoint=https://xxx.applicationinsights.azure.com/;..."
}Get connection string from: Azure Portal → Application Insights → Overview → Connection String
Step 2: Choose Telemetry Method
| Method | When to Use |
| Feature Telemetry (Recommended) | Standard logging with auto dimensions, uptake tracking |
| Session.LogMessage | Direct control, no duplicates, simple scenarios |
Step 3: Create Telemetry Logger (Required for Feature Telemetry)
CRITICAL: Exactly ONE per publisher!
codeunit <ID> "<PREFIX> Telemetry Logger" implements "Telemetry Logger"
{
Access = Internal;
procedure LogMessage(
EventId: Text;
Message: Text;
Verbosity: Verbosity;
DataClassification: DataClassification;
TelemetryScope: TelemetryScope;
CustomDimensions: Dictionary of [Text, Text])
begin
Session.LogMessage(EventId, Message, Verbosity, DataClassification,
TelemetryScope, CustomDimensions);
end;
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Telemetry Loggers",
'OnRegisterTelemetryLogger', '', true, true)]
local procedure OnRegisterTelemetryLogger(var Sender: Codeunit "Telemetry Loggers")
var
TelemetryLogger: Codeunit "<PREFIX> Telemetry Logger";
begin
Sender.Register(TelemetryLogger);
end;
}Step 4: Define EventId Convention
Format: <PREFIX>-<NNNN> (with hyphen to distinguish from BC standard)
Organization by Range:
| Range | Area | Convention |
| 00xx | Area 1 (e.g., API to System A) | Even = success, Odd = error |
| 01xx | Area 2 (e.g., API to System B) | Even = success, Odd = error |
| 02xx | Authentication | Even = success, Odd = error |
| 09xx | Fallback/Generic | For unmapped operations |
Example Registry:
| EventId | Operation | Result |
APP-0001 | SendOrder | Success |
APP-0002 | SendOrder | Error |
APP-0003 | SendLine | Success |
APP-0004 | SendLine | Error |
Step 5: Implement Logging
Using Feature Telemetry (Recommended)
var
FeatureTelemetry: Codeunit "Feature Telemetry";
CustomDimensions: Dictionary of [Text, Text];
begin
// Replace <Record> and field names with your source record
CustomDimensions.Add('<KeyFieldName>', <Record>."<KeyField>");
CustomDimensions.Add('<RelatedFieldName>', <Record>."<RelatedField>");
FeatureTelemetry.LogUsage('<PREFIX>-0001', '<FeatureName>', '<OperationDescription>', CustomDimensions);
FeatureTelemetry.LogError('<PREFIX>-0002', '<FeatureName>', '<OperationDescription>',
GetLastErrorText(), GetLastErrorCallStack(), CustomDimensions);
FeatureTelemetry.LogUptake('<PREFIX>-0010', '<FeatureName>',
Enum::"Feature Uptake Status"::Used);
end;Using Session.LogMessage (Direct)
var
CustomDimensions: Dictionary of [Text, Text];
begin
// Replace <Record> and field names with your source record
CustomDimensions.Add('<KeyFieldName>', <Record>."<KeyField>");
CustomDimensions.Add('Operation', '<OperationName>');
Session.LogMessage('<PREFIX>-0001', '<LogMessage>', Verbosity::Normal,
DataClassification::SystemMetadata, TelemetryScope::ExtensionPublisher, CustomDimensions);
end;Step 6: Hybrid Logging (Telemetry + Local Table)
For API integrations, use both:
- Telemetry: Synthetic data for monitoring/alerts
- Local Table: Complete JSON for debugging
See BC-Telemetry-Guide.md Section 14 for complete implementation.
Step 7: Query in Application Insights
Basic KQL Query:
traces
| where timestamp > ago(24h)
| where customDimensions.eventId startswith "AL<PREFIX>-"
| project
timestamp,
eventId = tostring(customDimensions.eventId),
message,
customDimensions
| order by timestamp descNote: Remember the AL prefix rule from Key Concept when searching in App Insights.
Important Notes
DataClassification: ALWAYS use SystemMetadata - other values won't be sent!
TelemetryScope: ExtensionPublisher = only your App Insights | All = yours AND customer's
Multi-App: ONE Telemetry Logger per publisher. Distinguish apps via alCallerAppName dimension.
Job Queue and Scheduled Task Telemetry
Job Queue entries trigger Scheduled Tasks at platform level. Key event IDs:
- Job Queue (AL):
AL0000E24(Enqueued),AL0000E25(Started),AL0000E26(Success),AL0000HE7(Failure) - Scheduled Task (LC):
LC0040-LC0045,LC0057(Created → Failed → Timeout)
Correlate via alScheduledTaskId dimension in AL0000E24.
See references/job-queue-telemetry.md for complete event tables and KQL queries.
Troubleshooting
| Issue | Fix |
| Events not appearing | Check applicationInsightsConnectionString in app.json |
| Wrong eventId in App Insights | Remember: platform adds AL prefix automatically |
| DataClassification error | MUST use SystemMetadata - other values won't send |
| Duplicate events | Feature Telemetry creates 2 by design - de-duplicate in KQL |
Feedback loop: Fix configuration → Re-deploy → Wait 5 minutes → Re-check in App Insights.
References
See references/ folder for:
kql-queries.md- Common KQL queriesjob-queue-telemetry.md- Job Queue and Scheduled Task monitoring
External Documentation
BC Telemetry:
- Microsoft: Telemetry Overview
- Microsoft: Telemetry Event IDs
- Microsoft: Feature Telemetry
- Microsoft: Custom Telemetry Events
- Microsoft: Task Scheduler
- BCTech Samples & KQL Queries
KQL Learning:
- MustLearnKQL - 21-part KQL tutorial series (Sentinel-focused but KQL syntax is universal)
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

