public ISegment StartDatastoreSegment(MethodCall methodCall, ParsedSqlStatement parsedSqlStatement, ConnectionInfo connectionInfo, string commandText, IDictionary <string, IConvertible> queryParameters = null, bool isLeaf = false) { #if DEBUG Log.Finest("Skipping StartDatastoreSegment outside of a transaction"); #endif return(Segment.NoOpSegment); }
public DatastoreSegmentData(IDatabaseService databaseService, ParsedSqlStatement parsedSqlStatement, string commandText = null, ConnectionInfo connectionInfo = null, IDictionary <string, IConvertible> queryParameters = null) { _databaseService = databaseService; _connectionInfo = connectionInfo ?? EmptyConnectionInfo; _parsedSqlStatement = parsedSqlStatement; CommandText = commandText; QueryParameters = queryParameters; }
public void SetUp() { _environment = Mock.Create <IEnvironment>(); _processStatic = Mock.Create <IProcessStatic>(); _httpRuntimeStatic = Mock.Create <IHttpRuntimeStatic>(); _configurationManagerStatic = Mock.Create <IConfigurationManagerStatic>(); _dnsStatic = Mock.Create <IDnsStatic>(); _securityPoliciesConfiguration = new SecurityPoliciesConfiguration(); _runTimeConfiguration = new RunTimeConfiguration(); _serverConfig = new ServerConfiguration(); SetLocalConfigurationDefaults(); PublishConfig(); _configAutoResponder = new ConfigurationAutoResponder(_config); _configurationService = Mock.Create <IConfigurationService>(); Mock.Arrange(() => _configurationService.Configuration).Returns(() => _config); _attribDefSvc = new AttributeDefinitionService((f) => new AttributeDefinitions(f)); _metricNameSvc = new MetricNameService(); _transactionMetricNameMaker = new TransactionMetricNameMaker(_metricNameSvc); _transactionAttribMaker = new TransactionAttributeMaker(_configurationService, _attribDefSvc); _spanEventMaker = new SpanEventMaker(_attribDefSvc, _configurationService); _databaseService = new DatabaseService(Mock.Create <ICacheStatsReporter>()); _transactionEventMaker = new TransactionEventMaker(_attribDefSvc); _transactionGuid = GuidGenerator.GenerateNewRelicGuid(); _startTime = new DateTime(2018, 7, 18, 7, 0, 0, DateTimeKind.Utc); // unixtime = 1531897200000 // Generic Segments _baseGenericSegment = new Segment(CreateTransactionSegmentState(3, null, 777), new MethodCallData(MethodCallType, MethodCallMethod, 1)); _baseGenericSegment.SetSegmentData(new SimpleSegmentData(SegmentName)); _childGenericSegment = new Segment(CreateTransactionSegmentState(4, 3, 777), new MethodCallData(MethodCallType, MethodCallMethod, 1)); _childGenericSegment.SetSegmentData(new SimpleSegmentData(SegmentName)); // Datastore Segments _connectionInfo = new ConnectionInfo("localhost", "1234", "default", "maininstance"); _parsedSqlStatement = SqlParser.GetParsedDatabaseStatement(DatastoreVendor.MSSQL, System.Data.CommandType.Text, ShortQuery); _obfuscatedSql = _databaseService.GetObfuscatedSql(ShortQuery, DatastoreVendor.MSSQL); _baseDatastoreSegment = new Segment(CreateTransactionSegmentState(3, null, 777), new MethodCallData(MethodCallType, MethodCallMethod, 1)); _baseDatastoreSegment.SetSegmentData(new DatastoreSegmentData(_databaseService, _parsedSqlStatement, ShortQuery, _connectionInfo)); // Http Segments _baseHttpSegment = new Segment(CreateTransactionSegmentState(3, null, 777), new MethodCallData(MethodCallType, MethodCallMethod, 1)); _baseHttpSegment.SetSegmentData(new ExternalSegmentData(new Uri(HttpUri), HttpMethod)); }
public void GetSpanEvent_ReturnsSpanEventPerSegment_DatastoreTruncateLongStatement() { var customerStmt = new string[] { new string('U', 2015), //1-byte per char new string('仮', 1015) //3-bytes per char }; var expectedStmtTrunc = new string[] { new string('U', 1996) + "...", //1-byte per char new string('仮', 666) + "..." //3-bytes per char }; for (int i = 0; i < customerStmt.Length; i++) { // ARRANGE var longSqlStatement = new ParsedSqlStatement(DatastoreVendor.MSSQL, customerStmt[i], "select"); var longDatastoreSegment = new Segment(CreateTransactionSegmentState(3, null, 777), new MethodCallData(MethodCallType, MethodCallMethod, 1)); longDatastoreSegment.SetSegmentData(new DatastoreSegmentData(_databaseService, longSqlStatement, customerStmt[i], _connectionInfo)); var segments = new List <Segment>() { longDatastoreSegment.CreateSimilar(TimeSpan.FromMilliseconds(1), TimeSpan.FromMilliseconds(5), new List <KeyValuePair <string, object> >()), }; var immutableTransaction = BuildTestTransaction(segments, true, false); var transactionMetricName = _transactionMetricNameMaker.GetTransactionMetricName(immutableTransaction.TransactionName); var metricStatsCollection = new TransactionMetricStatsCollection(transactionMetricName); var transactionAttribs = _transactionAttribMaker.GetAttributes(immutableTransaction, transactionMetricName, TimeSpan.FromSeconds(1), immutableTransaction.Duration, metricStatsCollection); // ACT var spanEvents = _spanEventMaker.GetSpanEvents(immutableTransaction, TransactionName, transactionAttribs); var spanEvent = spanEvents.ToList()[1]; // ASSERT var attribStatement = (string)spanEvent.AgentAttributes()["db.statement"]; var attribStmtLenBytes = Encoding.UTF8.GetByteCount(attribStatement); Assert.AreEqual(expectedStmtTrunc[i], attribStatement); Assert.True(attribStmtLenBytes <= 1999); Assert.True(attribStmtLenBytes >= 1996); } }
public AfterWrappedMethodDelegate BeforeWrappedMethod(InstrumentedMethodCall instrumentedMethodCall, IAgent agent, ITransaction transaction) { if (instrumentedMethodCall.IsAsync) { transaction.AttachToAsync(); } var operation = Common.GetRedisCommand(instrumentedMethodCall.MethodCall, AssemblyName); var connectionInfo = Common.GetConnectionInfoFromConnectionMultiplexer(instrumentedMethodCall.MethodCall, AssemblyName); var segment = transaction.StartDatastoreSegment(instrumentedMethodCall.MethodCall, ParsedSqlStatement.FromOperation(DatastoreVendor.Redis, operation), connectionInfo); //We're not using Delegates.GetAsyncDelegateFor(agent, segment) because if an async redis call is made from an asp.net mvc action, //the continuation may not run until that mvc action has finished executing, or has yielded execution, because the synchronization context //will only allow one thread to execute at a time. To work around this limitation, since we don't need access to HttpContext in our continuation, //we can just provide the TaskContinuationOptions.HideScheduler flag so that we will use the default ThreadPool scheduler to schedule our //continuation. Using the ThreadPool scheduler allows our continuation to run without needing to wait for the mvc action to finish executing or //yielding its execution. We're not applying this change across the board, because we still need to better understand the impact of making this //change more broadly vs just fixing a known customer issue. return(Delegates.GetAsyncDelegateFor <Task>(agent, segment, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.HideScheduler)); }
public AfterWrappedMethodDelegate BeforeWrappedMethod(InstrumentedMethodCall instrumentedMethodCall, IAgent agent, ITransaction transaction) { var operation = GetOperationName(instrumentedMethodCall.MethodCall); var segment = transaction.StartDatastoreSegment(instrumentedMethodCall.MethodCall, ParsedSqlStatement.FromOperation(DatastoreVendor.MongoDB, operation)); return(Delegates.GetDelegateFor(segment)); }
public AfterWrappedMethodDelegate BeforeWrappedMethod(InstrumentedMethodCall instrumentedMethodCall, IAgent agent, ITransaction transaction) { var redisCommandWithArgumentsAsBytes = instrumentedMethodCall.MethodCall.MethodArguments.ExtractNotNullAs <byte[][]>(0); var redisCommand = redisCommandWithArgumentsAsBytes[0]; if (redisCommand == null) { return(Delegates.NoOp); } var operation = GetRedisCommand(redisCommand); var contextObject = instrumentedMethodCall.MethodCall.InvocationTarget; if (contextObject == null) { throw new NullReferenceException(nameof(contextObject)); } var host = TryGetPropertyName(PropertyHost, contextObject) ?? "unknown"; host = ConnectionStringParserHelper.NormalizeHostname(host); var portPathOrId = TryGetPropertyName(PropertyPortPathOrId, contextObject); var databaseName = TryGetPropertyName(PropertyDatabaseName, contextObject); var connectionInfo = new ConnectionInfo(host, portPathOrId, databaseName); var segment = transaction.StartDatastoreSegment(instrumentedMethodCall.MethodCall, ParsedSqlStatement.FromOperation(DatastoreVendor.Redis, operation), connectionInfo); return(Delegates.GetDelegateFor(segment)); }
public AfterWrappedMethodDelegate BeforeWrappedMethod(InstrumentedMethodCall instrumentedMethodCall, IAgent agent, ITransaction transaction) { var operation = Common.GetRedisCommand(instrumentedMethodCall.MethodCall, AssemblyName); var connectionInfo = Common.GetConnectionInfoFromConnectionMultiplexer(instrumentedMethodCall.MethodCall, AssemblyName); var segment = transaction.StartDatastoreSegment(instrumentedMethodCall.MethodCall, ParsedSqlStatement.FromOperation(DatastoreVendor.Redis, operation), connectionInfo); return(Delegates.GetDelegateFor(segment)); }
public static VendorExplainValidationResult ShouldGenerateExplainPlan(string sql, ParsedSqlStatement parsedSqlStatement) { var validationMessage = ""; var isValid = true; var isSelectStatement = parsedSqlStatement.Operation.Equals("select", StringComparison.CurrentCultureIgnoreCase); if (!isSelectStatement) { validationMessage += "Will not run EXPLAIN on non-select statements. "; isValid = false; } var isSingleStatement = SqlParser.IsSingleSqlStatement(sql); if (!isSingleStatement) { validationMessage += "Will not run EXPLAIN on multi-statement SQL query. "; isValid = false; } return(new VendorExplainValidationResult(isValid, validationMessage)); }