// Illustrative; not run against live data. Azure Monitor Log Analytics, Azure API Management (resource-specific logs). // For your own app: callers that read many different customer records through an endpoint meant to return the caller's own data. // A normal user reads one record, their own. A scraper reads thousands. Set the operation or path of your profile endpoint. let Since = ago(30d); let ProfileOperation = @"(?i)REPLACE_WITH_PROFILE_OPERATION_OR_PATH"; ApiManagementGatewayLogs | where TimeGenerated > Since | where ResponseCode == 200 | where OperationId matches regex ProfileOperation or Url matches regex ProfileOperation | extend ObjectId = extract(@"/(\d{4,}|[0-9a-fA-F-]{32,36})(?:[/?]|$)", 1, Url) | summarize Requests = count(), DistinctObjects = dcount(ObjectId), DistinctUsers = dcount(UserId), ResponseMB = round(sum(ResponseSize) / 1048576.0, 1), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by CallerIpAddress, bin(TimeGenerated, 1h) | where DistinctObjects > 50 or DistinctUsers > 20 or Requests > 1000 | order by Requests desc | take 500