分享方式:


在 Application Insights SDK 中篩選及前置處理遙測

在從 SDK 傳送遙測資料之前,您可以撰寫程式碼來篩選、修改或擴充遙測資料。 處理包括從標準遙測模組 (如 HTTP 要求收集和相依性收集) 的資料。

  • 篩選可以先修改或捨棄遙測,再藉由實作 ITelemetryProcessor 從 SDK 傳送遙測。 例如,您可以從傀儡程式中排除要求來減少遙測量。 與取樣不同,您可以完全控制傳送或捨棄的內容,但它會影響以彙總記錄為基礎的任何計量。 視您捨棄項目的方式而定,您也可能會喪失在相關項目之間瀏覽的能力。

  • 透過實作 ITelemetryInitializer,對從您的應用程式中所傳送的任何遙測資料新增或修改屬性。 例如,您可以新增計算好的值,或是用來在入口網站中篩選資料的版本號碼。

  • 取樣 可減少遙測的量而不會影響統計資料。 其可將相關資料點寶持放在一起,因此您診斷問題時,能夠在資料點之間瀏覽。 在入口網站中將乘以總計數,以補償取樣。

注意

SDK API 可用來傳送自訂事件和計量。

必要條件

為您的應用程式安裝適當的 SDK:ASP.NETASP.NET Core適用於 .NET/.NET Core 的非 HTTP/背景工作角色JavaScript

篩選

這項技術可讓您直接地控制包含在遙測串流中或排除於遙測串流外的內容。 篩選可用來捨棄遙測項目,不讓其傳送至 Application Insights。 您可以將篩選與取樣搭配使用或分開使用。

若要篩選遙測,請撰寫遙測處理器,並向 TelemetryConfiguration 進行註冊。 所有遙測都會通過您的處理器。 您可以選擇從資料流中捨棄遙測,或將遙測提供給鏈結中的下一個處理器。 來自標準模組 (例如 HTTP 要求收集器和相依性收集器) 的遙測,以及您自行追蹤的遙測都包括在內。 例如,您可以篩選掉有關來自傀儡程式要求或成功的相依性呼叫的遙測。

警告

使用處理器來篩選 SDK 傳送過來的遙測可能會曲解您在入口網站中看到的統計資料,並且難以追蹤相關的項目。

請考慮改用 取樣

.NET 應用程式

  1. 實作 ITelemetryProcessor

    遙測處理器會建構一連串的處理。 當您具現化遙測處理器時,所獲得的是鏈結中下一個處理器的參考。 遙測資料點傳遞至處理序方法時,其會完成其工作並接著呼叫 (或不呼叫) 鏈結中的下一個遙測處理器。

    using Microsoft.ApplicationInsights.Channel;
    using Microsoft.ApplicationInsights.Extensibility;
    using Microsoft.ApplicationInsights.DataContracts;
    
    public class SuccessfulDependencyFilter : ITelemetryProcessor
    {
        private ITelemetryProcessor Next { get; set; }
    
        // next will point to the next TelemetryProcessor in the chain.
        public SuccessfulDependencyFilter(ITelemetryProcessor next)
        {
            this.Next = next;
        }
    
        public void Process(ITelemetry item)
        {
            // To filter out an item, return without calling the next processor.
            if (!OKtoSend(item)) { return; }
    
            this.Next.Process(item);
        }
    
        // Example: replace with your own criteria.
        private bool OKtoSend (ITelemetry item)
        {
            var dependency = item as DependencyTelemetry;
            if (dependency == null) return true;
    
            return dependency.Success != true;
        }
    }
    
  2. 新增您的處理器。

    在 ApplicationInsights.config 中插入此程式碼片段:

    <TelemetryProcessors>
      <Add Type="WebApplication9.SuccessfulDependencyFilter, WebApplication9">
        <!-- Set public property -->
        <MyParamFromConfigFile>2-beta</MyParamFromConfigFile>
      </Add>
    </TelemetryProcessors>
    

    您可以在類別中提供公開具名屬性,以從 .config 檔案傳遞字串值。

    警告

    仔細地將 .config 檔案中的類型名稱和任何屬性名稱與程式碼中的類別和屬性名稱做比對。 如果 .config 檔案參考不存在的類型或屬性,SDK 可能無法傳送任何遙測,而且不會產生任何訊息。

    或者,您也可以在程式碼中初始化篩選條件。 在適當的初始化類別中 (例如,Global.asax.cs 中的 AppStart) 將處理器插入至鏈結中:

    var builder = TelemetryConfiguration.Active.DefaultTelemetrySink.TelemetryProcessorChainBuilder;
    builder.Use((next) => new SuccessfulDependencyFilter(next));
    
    // If you have more processors:
    builder.Use((next) => new AnotherProcessor(next));
    
    builder.Build();
    

    在這個點之後建立的遙測用戶端會使用您的處理器。

範例篩選器

綜合要求

篩選出 bot 和 Web 測試。 雖然計量瀏覽器可讓您篩選掉綜合來源,此選項會藉由在 SDK 本身篩選其以降低流量和擷取大小。

public void Process(ITelemetry item)
{
    if (!string.IsNullOrEmpty(item.Context.Operation.SyntheticSource)) {return;}
    
    // Send everything else:
    this.Next.Process(item);
}

驗證失敗

篩選出具有 "401" 回應的要求。

public void Process(ITelemetry item)
{
    var request = item as RequestTelemetry;

    if (request != null &&
    request.ResponseCode.Equals("401", StringComparison.OrdinalIgnoreCase))
    {
        // To filter out an item, return without calling the next processor.
        return;
    }

    // Send everything else
    this.Next.Process(item);
}

篩選出快速遠端相依性呼叫

如果您只想要診斷速度很慢的呼叫,請篩選掉速度很快的呼叫。

注意

此篩選會曲解您在入口網站上看到的統計資料。

public void Process(ITelemetry item)
{
    var request = item as DependencyTelemetry;

    if (request != null && request.Duration.TotalMilliseconds < 100)
    {
        return;
    }
    this.Next.Process(item);
}

診斷相依性問題

這篇部落格文章 描述可自動傳送定期的 Ping 給相依項目,藉以診斷相依性問題的專案。

Java 應用程式

若要深入了解遙測處理器及其在 JAVA 中的實作,請參閱 JAVA 遙測處理器文件

JavaScript Web 應用程式

您可以使用 ITelemetryInitializer 從 JavaScript Web 應用程式篩選遙測資料。

  1. 建立遙測初始設定式回呼函式。 回呼函式會採用 ITelemetryItem 作為參數,這是會進行處理的事件。 從這個回呼傳回 false 會導致遙測項目遭到篩掉。

    var filteringFunction = (envelope) => {
      if (envelope.data.someField === 'tobefilteredout') {
        return false;
      }
      return true;
    };
    
  2. 新增遙測初始設定式回呼:

    appInsights.addTelemetryInitializer(filteringFunction);
    

新增/修改屬性︰ITelemetryInitializer

使用遙測初始設定式,利用其他資訊來擴充您的遙測,或覆寫由標準遙測模組所設定的遙測屬性。

例如,網頁套件的 Application Insights 會收集有關 HTTP 要求的遙測。 根據預設,它會將任何含回應碼 >=400 的要求標記為失敗。 如果您想改為將 400 視為成功,則可以提供設定 success 屬性的遙測初始設定式。

如果您提供遙測初始設定式,則會在呼叫任何的 Track*() 方法時呼叫。 此初始設定式包括由標準遙測模組呼叫的 Track() 方法。 依照慣例,這些模組不會設定任何已由初始設定式設定的屬性。 在呼叫遙測處理器之前會呼叫遙測初始設定式,因此初始設定式完成的任何擴充對處理器都是可見的。

.NET 應用程式

  1. 定義您的初始設定式

    using System;
    using Microsoft.ApplicationInsights.Channel;
    using Microsoft.ApplicationInsights.DataContracts;
    using Microsoft.ApplicationInsights.Extensibility;
    
    namespace MvcWebRole.Telemetry
    {
      /*
       * Custom TelemetryInitializer that overrides the default SDK
       * behavior of treating response codes >= 400 as failed requests
       *
       */
        public class MyTelemetryInitializer : ITelemetryInitializer
        {
            public void Initialize(ITelemetry telemetry)
            {
                var requestTelemetry = telemetry as RequestTelemetry;
                // Is this a TrackRequest() ?
                if (requestTelemetry == null) return;
                int code;
                bool parsed = Int32.TryParse(requestTelemetry.ResponseCode, out code);
                if (!parsed) return;
                if (code >= 400 && code < 500)
                {
                    // If we set the Success property, the SDK won't change it:
                    requestTelemetry.Success = true;
    
                    // Allow us to filter these requests in the portal:
                    requestTelemetry.Properties["Overridden400s"] = "true";
                }
                // else leave the SDK to set the Success property
            }
        }
    }
    
  2. 載入您的初始設定式

    在 ApplicationInsights.config 中:

    <ApplicationInsights>
      <TelemetryInitializers>
        <!-- Fully qualified type name, assembly name: -->
        <Add Type="MvcWebRole.Telemetry.MyTelemetryInitializer, MvcWebRole"/>
        ...
      </TelemetryInitializers>
    </ApplicationInsights>
    

    或者,您也可以在程式碼 (如 Global.aspx.cs) 中具現化初始設定式:

    protected void Application_Start()
    {
        // ...
        TelemetryConfiguration.Active.TelemetryInitializers.Add(new MyTelemetryInitializer());
    }
    

    詳細查看此範例

JavaScript 遙測初始設定式

視需要插入 JavaScript 遙測初始設定式。 如需 Application Insights JavaScript SDK 遙測初始設定式的詳細資訊,請參閱遙測初始設定式

JavaScript (Web) SDK 載入器指令碼設定中新增 onInit 回呼函式,以插入遙測初始設定式:

<script type="text/javascript">
!(function (cfg){function e(){cfg.onInit&&cfg.onInit(n)}var x,w,D,t,E,n,C=window,O=document,b=C.location,q="script",I="ingestionendpoint",L="disableExceptionTracking",j="ai.device.";"instrumentationKey"[x="toLowerCase"](),w="crossOrigin",D="POST",t="appInsightsSDK",E=cfg.name||"appInsights",(cfg.name||C[t])&&(C[t]=E),n=C[E]||function(g){var f=!1,m=!1,h={initialize:!0,queue:[],sv:"8",version:2,config:g};function v(e,t){var n={},i="Browser";function a(e){e=""+e;return 1===e.length?"0"+e:e}return n[j+"id"]=i[x](),n[j+"type"]=i,n["ai.operation.name"]=b&&b.pathname||"_unknown_",n["ai.internal.sdkVersion"]="javascript:snippet_"+(h.sv||h.version),{time:(i=new Date).getUTCFullYear()+"-"+a(1+i.getUTCMonth())+"-"+a(i.getUTCDate())+"T"+a(i.getUTCHours())+":"+a(i.getUTCMinutes())+":"+a(i.getUTCSeconds())+"."+(i.getUTCMilliseconds()/1e3).toFixed(3).slice(2,5)+"Z",iKey:e,name:"Microsoft.ApplicationInsights."+e.replace(/-/g,"")+"."+t,sampleRate:100,tags:n,data:{baseData:{ver:2}},ver:undefined,seq:"1",aiDataContract:undefined}}var n,i,t,a,y=-1,T=0,S=["js.monitor.azure.com","js.cdn.applicationinsights.io","js.cdn.monitor.azure.com","js0.cdn.applicationinsights.io","js0.cdn.monitor.azure.com","js2.cdn.applicationinsights.io","js2.cdn.monitor.azure.com","az416426.vo.msecnd.net"],o=g.url||cfg.src,r=function(){return s(o,null)};function s(d,t){if((n=navigator)&&(~(n=(n.userAgent||"").toLowerCase()).indexOf("msie")||~n.indexOf("trident/"))&&~d.indexOf("ai.3")&&(d=d.replace(/(\/)(ai\.3\.)([^\d]*)$/,function(e,t,n){return t+"ai.2"+n})),!1!==cfg.cr)for(var e=0;e<S.length;e++)if(0<d.indexOf(S[e])){y=e;break}var n,i=function(e){var a,t,n,i,o,r,s,c,u,l;h.queue=[],m||(0<=y&&T+1<S.length?(a=(y+T+1)%S.length,p(d.replace(/^(.*\/\/)([\w\.]*)(\/.*)$/,function(e,t,n,i){return t+S[a]+i})),T+=1):(f=m=!0,s=d,!0!==cfg.dle&&(c=(t=function(){var e,t={},n=g.connectionString;if(n)for(var i=n.split(";"),a=0;a<i.length;a++){var o=i[a].split("=");2===o.length&&(t[o[0][x]()]=o[1])}return t[I]||(e=(n=t.endpointsuffix)?t.location:null,t[I]="https://"+(e?e+".":"")+"dc."+(n||"services.visualstudio.com")),t}()).instrumentationkey||g.instrumentationKey||"",t=(t=(t=t[I])&&"/"===t.slice(-1)?t.slice(0,-1):t)?t+"/v2/track":g.endpointUrl,t=g.userOverrideEndpointUrl||t,(n=[]).push((i="SDK LOAD Failure: Failed to load Application Insights SDK script (See stack for details)",o=s,u=t,(l=(r=v(c,"Exception")).data).baseType="ExceptionData",l.baseData.exceptions=[{typeName:"SDKLoadFailed",message:i.replace(/\./g,"-"),hasFullStack:!1,stack:i+"\nSnippet failed to load ["+o+"] -- Telemetry is disabled\nHelp Link: https://go.microsoft.com/fwlink/?linkid=2128109\nHost: "+(b&&b.pathname||"_unknown_")+"\nEndpoint: "+u,parsedStack:[]}],r)),n.push((l=s,i=t,(u=(o=v(c,"Message")).data).baseType="MessageData",(r=u.baseData).message='AI (Internal): 99 message:"'+("SDK LOAD Failure: Failed to load Application Insights SDK script (See stack for details) ("+l+")").replace(/\"/g,"")+'"',r.properties={endpoint:i},o)),s=n,c=t,JSON&&((u=C.fetch)&&!cfg.useXhr?u(c,{method:D,body:JSON.stringify(s),mode:"cors"}):XMLHttpRequest&&((l=new XMLHttpRequest).open(D,c),l.setRequestHeader("Content-type","application/json"),l.send(JSON.stringify(s)))))))},a=function(e,t){m||setTimeout(function(){!t&&h.core||i()},500),f=!1},p=function(e){var n=O.createElement(q),e=(n.src=e,t&&(n.integrity=t),n.setAttribute("data-ai-name",E),cfg[w]);return!e&&""!==e||"undefined"==n[w]||(n[w]=e),n.onload=a,n.onerror=i,n.onreadystatechange=function(e,t){"loaded"!==n.readyState&&"complete"!==n.readyState||a(0,t)},cfg.ld&&cfg.ld<0?O.getElementsByTagName("head")[0].appendChild(n):setTimeout(function(){O.getElementsByTagName(q)[0].parentNode.appendChild(n)},cfg.ld||0),n};p(d)}cfg.sri&&(n=o.match(/^((http[s]?:\/\/.*\/)\w+(\.\d+){1,5})\.(([\w]+\.){0,2}js)$/))&&6===n.length?(d="".concat(n[1],".integrity.json"),i="@".concat(n[4]),l=window.fetch,t=function(e){if(!e.ext||!e.ext[i]||!e.ext[i].file)throw Error("Error Loading JSON response");var t=e.ext[i].integrity||null;s(o=n[2]+e.ext[i].file,t)},l&&!cfg.useXhr?l(d,{method:"GET",mode:"cors"}).then(function(e){return e.json()["catch"](function(){return{}})}).then(t)["catch"](r):XMLHttpRequest&&((a=new XMLHttpRequest).open("GET",d),a.onreadystatechange=function(){if(a.readyState===XMLHttpRequest.DONE)if(200===a.status)try{t(JSON.parse(a.responseText))}catch(e){r()}else r()},a.send())):o&&r();try{h.cookie=O.cookie}catch(k){}function e(e){for(;e.length;)!function(t){h[t]=function(){var e=arguments;f||h.queue.push(function(){h[t].apply(h,e)})}}(e.pop())}var c,u,l="track",d="TrackPage",p="TrackEvent",l=(e([l+"Event",l+"PageView",l+"Exception",l+"Trace",l+"DependencyData",l+"Metric",l+"PageViewPerformance","start"+d,"stop"+d,"start"+p,"stop"+p,"addTelemetryInitializer","setAuthenticatedUserContext","clearAuthenticatedUserContext","flush"]),h.SeverityLevel={Verbose:0,Information:1,Warning:2,Error:3,Critical:4},(g.extensionConfig||{}).ApplicationInsightsAnalytics||{});return!0!==g[L]&&!0!==l[L]&&(e(["_"+(c="onerror")]),u=C[c],C[c]=function(e,t,n,i,a){var o=u&&u(e,t,n,i,a);return!0!==o&&h["_"+c]({message:e,url:t,lineNumber:n,columnNumber:i,error:a,evt:C.event}),o},g.autoExceptionInstrumented=!0),h}(cfg.cfg),(C[E]=n).queue&&0===n.queue.length?(n.queue.push(e),n.trackPageView({})):e();})({
src: "https://js.monitor.azure.com/scripts/b/ai.3.gbl.min.js",
crossOrigin: "anonymous", // When supplied this will add the provided value as the cross origin attribute on the script tag
onInit: function (sdk) {
    sdk.addTelemetryInitializer(function (envelope) {
    envelope.data = envelope.data || {};
    envelope.data.someField = 'This item passed through my telemetry initializer';
    });
}, // Once the application insights instance has loaded and initialized this method will be called
// sri: false, // Custom optional value to specify whether fetching the snippet from integrity file and do integrity check
cfg: { // Application Insights Configuration
    connectionString: "YOUR_CONNECTION_STRING"
}});
</script>

如需遙測項目上可用的非自訂屬性摘要,請參閱 Application Insights 匯出資料模型

您可以依需要加入多個初始設定式。 系統會依其新增順序來進行呼叫。

OpenCensus Python 遙測處理器

OpenCensus Python 中的遙測處理器就是回呼函式,系統會呼叫其來處理遙測再將遙測匯出。 回呼函式必須以信封資料類型作為其參數。 若要篩選掉不要匯出的遙測,請確定回呼函式傳回的是 False。 您可以在 GitHub 上的信封中查看 Azure 監視器資料類型的結構描述。

注意

您可以藉由變更 tags 欄位中的 ai.cloud.role 屬性來修改 cloud_RoleName

def callback_function(envelope):
    envelope.tags['ai.cloud.role'] = 'new_role_name'
# Example for log exporter
import logging

from opencensus.ext.azure.log_exporter import AzureLogHandler

logger = logging.getLogger(__name__)

# Callback function to append '_hello' to each log message telemetry
def callback_function(envelope):
    envelope.data.baseData.message += '_hello'
    return True

handler = AzureLogHandler(connection_string='InstrumentationKey=<your-instrumentation_key-here>')
handler.add_telemetry_processor(callback_function)
logger.addHandler(handler)
logger.warning('Hello, World!')
# Example for trace exporter
import requests

from opencensus.ext.azure.trace_exporter import AzureExporter
from opencensus.trace import config_integration
from opencensus.trace.samplers import ProbabilitySampler
from opencensus.trace.tracer import Tracer

config_integration.trace_integrations(['requests'])

# Callback function to add os_type: linux to span properties
def callback_function(envelope):
    envelope.data.baseData.properties['os_type'] = 'linux'
    return True

exporter = AzureExporter(
    connection_string='InstrumentationKey=<your-instrumentation-key-here>'
)
exporter.add_telemetry_processor(callback_function)
tracer = Tracer(exporter=exporter, sampler=ProbabilitySampler(1.0))
with tracer.span(name='parent'):
response = requests.get(url='https://www.wikipedia.org/wiki/Rabbit')
# Example for metrics exporter
import time

from opencensus.ext.azure import metrics_exporter
from opencensus.stats import aggregation as aggregation_module
from opencensus.stats import measure as measure_module
from opencensus.stats import stats as stats_module
from opencensus.stats import view as view_module
from opencensus.tags import tag_map as tag_map_module

stats = stats_module.stats
view_manager = stats.view_manager
stats_recorder = stats.stats_recorder

CARROTS_MEASURE = measure_module.MeasureInt("carrots",
                                            "number of carrots",
                                            "carrots")
CARROTS_VIEW = view_module.View("carrots_view",
                                "number of carrots",
                                [],
                                CARROTS_MEASURE,
                                aggregation_module.CountAggregation())

# Callback function to only export the metric if value is greater than 0
def callback_function(envelope):
    return envelope.data.baseData.metrics[0].value > 0

def main():
    # Enable metrics
    # Set the interval in seconds in which you want to send metrics
    exporter = metrics_exporter.new_metrics_exporter(connection_string='InstrumentationKey=<your-instrumentation-key-here>')
    exporter.add_telemetry_processor(callback_function)
    view_manager.register_exporter(exporter)

    view_manager.register_view(CARROTS_VIEW)
    mmap = stats_recorder.new_measurement_map()
    tmap = tag_map_module.TagMap()

    mmap.measure_int_put(CARROTS_MEASURE, 1000)
    mmap.record(tmap)
    # Default export interval is every 15.0s
    # Your application should run for at least this amount
    # of time so the exporter will meet this interval
    # Sleep can fulfill this
    time.sleep(60)

    print("Done recording metrics")

if __name__ == "__main__":
    main()

您可以依照需要新增任意數量的處理器。 系統會依其新增順序來進行呼叫。 如果某個處理器擲回例外狀況,這並不會影響之後的處理器。

範例 TelemetryInitializers

新增自訂屬性

下列範例初始設定式會將自訂屬性新增至每個所追蹤的遙測。

public void Initialize(ITelemetry item)
{
    var itemProperties = item as ISupportProperties;
    if(itemProperties != null && !itemProperties.Properties.ContainsKey("customProp"))
    {
        itemProperties.Properties["customProp"] = "customValue";
    }
}

新增雲端角色名稱

下列範例初始設定式會將雲端角色名稱設定為每個所追蹤的遙測。

public void Initialize(ITelemetry telemetry)
{
    if (string.IsNullOrEmpty(telemetry.Context.Cloud.RoleName))
    {
        telemetry.Context.Cloud.RoleName = "MyCloudRoleName";
    }
}

控制用於地理位置對應的用戶端 IP 位址

在遙測擷取期間,下列初始設定式範例會設定用於地理位置對應的用戶端 IP,而不是用戶端通訊端 IP 位址。

public void Initialize(ITelemetry telemetry)
{
    var request = telemetry as RequestTelemetry;
    if (request == null) return true;
    request.Context.Location.Ip = "{client ip address}"; // Could utilize System.Web.HttpContext.Current.Request.UserHostAddress;   
    return true;
}

ITelemetryProcessor 和 ITelemetryInitializer

遙測處理器與遙測初始設定式之間有何差異?

  • 其用途有部分重疊。 兩者都可以用來新增或修改遙測的屬性,但建議您使用初始設定式來進行該作業。
  • 遙測初始設定式一律會比遙測處理器更早執行。
  • 遙測初始設定式可以多次呼叫。 依照慣例,其不會設定任何已經設定的屬性。
  • 遙測處理器可讓您完全取代或捨棄遙測項目。
  • 所有已註冊的遙測初始設定式都會針對每個遙測項目而受系統呼叫。 若為遙測處理器,SDK 保證會呼叫第一個遙測處理器。 是否會呼叫其餘處理器則由前面的遙測處理器決定。
  • 使用遙測初始設定式,利用更多屬性擴充遙測或覆寫現有的遙測。 使用遙測處理器來篩選掉遙測。

注意

JavaScript 只有遙測初始設定式,其可以使用 ITelemetryInitializer 來篩選掉事件

針對 ApplicationInsights.config 進行疑難排解

  • 確認完整格式的類型名稱和組件名稱均正確。
  • 確認 applicationinsights.config 檔案在您的輸出目錄中,並且包含任何最近的變更。

Azure 監視器遙測資料類型參考

參考文件

SDK 程式碼

下一步