예제 #1
0
        public void When_all_sensors_are_requested_and_some_are_slow_async_they_are_combined_with_synchronous_sensors()
        {
            var testSensor    = Any.Paragraph(5);
            var dynamicSensor = Any.Paragraph(7);

            TestSensor.GetSensorValue = () => Task.Run(() =>
            {
                Thread.Sleep(Any.Int(3000, 5000));
                return(testSensor);
            });

            DiagnosticSensor.Register(() => Task.Run(() =>
            {
                Thread.Sleep(Any.Int(3000, 5000));
                return(dynamicSensor);
            }), sensorName);

            var result = apiClient.GetStringAsync("http://blammo.com/sensors/").Result;

            Console.WriteLine(result);

            result.Should()
            .Contain(string.Format("\"SensorMethod\":\"{0}\"", testSensor))
            .And
            .Contain(string.Format("\"{0}\":\"{1}\"", sensorName, dynamicSensor));
        }
예제 #2
0
        public void Missing_assemblies_do_not_cause_sensor_discovery_to_fail()
        {
            // force loading of the problem assembly. this assembly has a dependency which is deliberately not included in the project so that unprotected MEF usage will trigger a TypeLoadException. sensor discovery is intended to ignore this issue and swallow the exception.
            var o = new ClassWithoutReferenceToMissingAssembly();

            DiagnosticSensor.Discover().Count().Should().BeGreaterThan(0);
        }
예제 #3
0
        public void Sensor_methods_are_invoked_per_Read_call()
        {
            var first  = DiagnosticSensor.KnownSensors().Single(s => s.Name == "CounterSensor").Read();
            var second = DiagnosticSensor.KnownSensors().Single(s => s.Name == "CounterSensor").Read();

            Assert.That(first, Is.Not.EqualTo(second));
        }
예제 #4
0
        /// <summary>
        /// Reads all sensors.
        /// </summary>
        /// <returns>The values returned by all sensors.</returns>
        public async Task <HttpResponseMessage> Get()
        {
            var readings = DiagnosticSensor.KnownSensors().ToDictionary(s => s.Name, s => s.Read());

            var asyncSensors = readings.Where(pair => pair.Value is Task).ToArray();

            if (asyncSensors.Any())
            {
                await Task.WhenAll(asyncSensors.Select(pair => pair.Value).OfType <Task>());
            }

            foreach (var pair in asyncSensors)
            {
                readings[pair.Key] = ((dynamic)pair.Value).Result;
            }

            // add a self link
            var localPath = ControllerContext.Request.RequestUri.LocalPath;
            var links     = new Dictionary <string, string>
            {
                { "self", localPath }
            };

            foreach (var sensorName in readings.Keys)
            {
                links.Add(sensorName, localPath.AppendSegment(sensorName.ToLowerInvariant()));
            }

            readings["_links"] = links;

            return(ControllerContext.Request.CreateResponse(HttpStatusCode.OK, readings, formatter));
        }
예제 #5
0
        public void When_registered_sensor_is_a_method_then_name_is_derived_from_its_name()
        {
            DiagnosticSensor.Register(SensorNameTester);

            Assert.That(
                DiagnosticSensor.KnownSensors().Count(s => s.Name == "SensorNameTester"),
                Is.EqualTo(1));
        }
예제 #6
0
        public async Task Sensor_methods_are_invoked_per_Read_call()
        {
            var first = await DiagnosticSensor.DiscoverSensors().Single(s => s.Name == "CounterSensor").Read();

            var second = await DiagnosticSensor.DiscoverSensors().Single(s => s.Name == "CounterSensor").Read();

            first.Should().NotBe(second);
        }
예제 #7
0
        /// <summary>
        /// Reads the specified sensor.
        /// </summary>
        /// <param name="name">The name of the sensor to read.</param>
        /// <returns>The value returned by the sensor.</returns>
        public async Task <HttpResponseMessage> Get(string name)
        {
            var sensor = DiagnosticSensor
                         .KnownSensors()
                         .SingleOrDefault(s => string.Equals(s.Name, name, StringComparison.OrdinalIgnoreCase));

            if (sensor == null)
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }

            var reading = sensor.Read();

            var readingTask = reading as Task;

            if (readingTask != null)
            {
                await readingTask;
                if (readingTask.GetType().GetGenericArguments().First().IsVisible)
                {
                    reading = ((dynamic)readingTask).Result;
                }
                else
                {
                    // this is required to work around the fact that internal types cause dynamic calls to Result to fail. JSON.NET however will happily serialize them, at which point we can retrieve the Result property.
                    var serialized = JsonConvert.SerializeObject(reading, jsonSerializerSettings);
                    reading = JsonConvert.DeserializeObject <dynamic>(serialized).Result;
                }
            }

            var responseCode = reading is Exception
                                   ? HttpStatusCode.InternalServerError
                                   : HttpStatusCode.OK;

            // add a self link
            var localPath = ControllerContext.Request.RequestUri.LocalPath;

            reading
            .IfTypeIs <IDictionary <string, object> >()
            .ThenDo(d => d["_links"] = new { self = localPath })
            .ElseDo(() =>
            {
                var json = JsonConvert.SerializeObject(reading, jsonSerializerSettings);

                if (!json.Contains("{"))
                {
                    json = @"{""value"":" + json + @"}";
                }

                var jtoken = JsonConvert.DeserializeObject <JToken>(json);

                jtoken.IfTypeIs <JObject>()
                .ThenDo(o => o.Add("_links", new JObject(new JProperty("self", localPath))));

                reading = jtoken;
            });
            return(ControllerContext.Request.CreateResponse(responseCode, reading, formatter));
        }
예제 #8
0
        public async Task When_sensor_throws_an_exception_then_the_exception_is_returned()
        {
            var result = (await DiagnosticSensor.DiscoverSensors()
                          .Single(s => s.Name == "ExceptionSensor")
                          .Read())
                         .Exception;

            result.Should().BeOfType <DataMisalignedException>();
        }
예제 #9
0
        public void Authorization_can_be_denied_for_all_sensors()
        {
            var configuration = new HttpConfiguration().MapSensorRoutes(ctx => false);
            var apiClient     = new HttpClient(new HttpServer(configuration));

            DiagnosticSensor.Register(() => "hello", sensorName);

            apiClient.GetAsync("http://blammo.com/sensors/" + sensorName).Result.StatusCode.Should().Be(HttpStatusCode.Forbidden);
        }
예제 #10
0
        public SensorRoutingTests()
        {
            registry = new SensorRegistry(DiagnosticSensor.DiscoverSensors());

            var peaky = new PeakyService(configureServices: s => s.AddSingleton(registry));

            apiClient = peaky.CreateHttpClient();

            sensorName = Any.AlphanumericString(10, 20);
        }
예제 #11
0
        public void When_a_sensor_returns_a_Task_then_its_IsAsync_Property_returns_true()
        {
            var sensorName = Any.Paragraph(5);

            DiagnosticSensor.Register(AsyncTask, sensorName);

            var sensor = DiagnosticSensor.KnownSensors().Single(s => s.Name == sensorName);

            sensor.IsAsync.Should().BeTrue();
        }
예제 #12
0
        public void When_registered_sensor_is_anonymous_then_DeclaringType_is_the_containing_type()
        {
            var newGuid = Guid.NewGuid();

            DiagnosticSensor.Register(() => newGuid);

            var sensor = DiagnosticSensor.KnownSensors().Single(s => s.Read().Equals(newGuid));

            Assert.That(sensor.DeclaringType, Is.EqualTo(GetType()));
        }
예제 #13
0
        public void When_registered_sensor_is_anonymous_then_default_name_is_derived_from_method_doing_registration()
        {
            var newGuid = Guid.NewGuid();

            DiagnosticSensor.Register(() => newGuid);

            var sensor = DiagnosticSensor.KnownSensors().Single(s => s.Read().Equals(newGuid));

            Assert.That(sensor.Name, Is.StringContaining(MethodBase.GetCurrentMethod().Name));
        }
예제 #14
0
        public void When_registered_sensor_is_a_method_then_DeclaringType_is_the_containing_type()
        {
            DiagnosticSensor.Register(StaticTestSensors.ExceptionSensor);

            var sensor = DiagnosticSensor.KnownSensors().Single(s => s.Name == "ExceptionSensor");

            Assert.That(
                sensor.DeclaringType,
                Is.EqualTo(typeof(StaticTestSensors)));
        }
예제 #15
0
        public void When_a_sensor_does_not_return_a_Task_then_its_IsAsync_Property_returns_false()
        {
            var sensorName = Any.Paragraph(5);

            DiagnosticSensor.Register(() => "hi!", sensorName);

            var sensor = DiagnosticSensor.KnownSensors().Single(s => s.Name == sensorName);

            sensor.IsAsync.Should().BeFalse();
        }
예제 #16
0
        public void Sensors_are_available_by_name()
        {
            var words = Any.Paragraph(5);

            DiagnosticSensor.Register(() => new { words }, sensorName);

            var response = apiClient.GetStringAsync("http://blammo.com/sensors/" + sensorName).Result;

            Console.WriteLine(response);

            response.Should().Contain(words);
        }
예제 #17
0
        public void Sensors_can_be_registered_at_runtime()
        {
            var sensorName = MethodBase.GetCurrentMethod().Name;

            DiagnosticSensor.Register(() => "hello", sensorName);

            var sensor = DiagnosticSensor.KnownSensors().Single(s => s.Name == sensorName);

            Assert.That(sensor.DeclaringType, Is.EqualTo(GetType()));
            Assert.That(sensor.ReturnType, Is.EqualTo(typeof(string)));
            Assert.That(sensor.Read(), Is.EqualTo("hello"));
        }
예제 #18
0
        public void When_a_sensor_returning_a_Task_is_requested_specifically_then_the_Result_is_returned()
        {
            var words = Any.Paragraph(5);

            DiagnosticSensor.Register(() => Task.Run(() => words), sensorName);

            dynamic result = JObject.Parse(apiClient.GetStringAsync("http://blammo.com/sensors/" + sensorName).Result);

            ((string)result.value)
            .Should()
            .Be(words);
        }
예제 #19
0
        public void Specific_sensor_content_includes_link_to_sensor_when_sensor_is_object()
        {
            DiagnosticSensor.Register(() => new FileInfo("c:\\temp\\foo.txt"), sensorName);
            var response = apiClient.GetStringAsync("http://blammo.com/sensors/" + sensorName).Result;

            dynamic sensorValue = JObject.Parse(response);

            Console.WriteLine(response);
            string selfLink = sensorValue._links.self;

            selfLink.Should().Be("/sensors/" + sensorName);
        }
예제 #20
0
        public void when_all_sensors_are_requested_and_one_throws_then_it_returns_200_and_the_exception_text_is_in_the_response_body()
        {
            DiagnosticSensor.Register <string>(() => { throw new Exception("oops!"); }, sensorName);

            var result = apiClient.GetAsync("http://blammo.com/sensors/").Result;

            var body = result.Content.ReadAsStringAsync().Result;

            result.StatusCode
            .Should().Be(HttpStatusCode.OK);
            body.Should().Contain("oops!");
        }
예제 #21
0
        public void Discovered_sensors_can_be_removed_at_runtime()
        {
            Assert.That(
                DiagnosticSensor.KnownSensors().Count(s => s.Name == "Sensor_for_Discovered_sensors_can_be_removed_at_runtime"),
                Is.EqualTo(1));

            DiagnosticSensor.Remove("Sensor_for_Discovered_sensors_can_be_removed_at_runtime");

            Assert.That(
                DiagnosticSensor.KnownSensors().Count(s => s.Name == "Sensor_for_Discovered_sensors_can_be_removed_at_runtime"),
                Is.EqualTo(0));
        }
예제 #22
0
        public void Registered_sensors_can_be_removed_at_runtime()
        {
            DiagnosticSensor.Register(SensorNameTester);

            Assert.That(
                DiagnosticSensor.KnownSensors().Count(s => s.Name == "SensorNameTester"),
                Is.EqualTo(1));

            DiagnosticSensor.Remove("SensorNameTester");

            Assert.That(
                DiagnosticSensor.KnownSensors().Count(s => s.Name == "SensorNameTester"),
                Is.EqualTo(0));
        }
예제 #23
0
        public void ReflectionTypeLoadException_due_to_missing_assembly_is_signalled_by_sensor_output()
        {
            // force loading of the problem assembly. this assembly has a dependency which is deliberately not included in the project so that unprotected MEF usage will trigger a TypeLoadException. sensor discovery is intended to ignore this issue and swallow the exception.
            var o = new ClassWithoutReferenceToMissingAssembly();

            dynamic reading = DiagnosticSensor.Discover()
                              .Values
                              .Select(s => s.Read())
                              .OfType <ReflectionTypeLoadException>()
                              .First();

            var loaderException = ((IEnumerable <Exception>)reading.LoaderExceptions).Single();

            loaderException.Message.Should().Contain("Could not load file or assembly 'MissingDependency, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e9ed0c9abcf549e2' or one of its dependencies. The system cannot find the file specified.");
        }
예제 #24
0
        public void KnownSensors_is_safe_to_modify_while_being_enumerated()
        {
            StaticTestSensors.Barrier = new Barrier(2);
            DiagnosticSensor.Register(() => "hello", MethodBase.GetCurrentMethod().Name);
            new Thread(() =>
            {
                DiagnosticSensor.KnownSensors().Select(s =>
                {
                    Console.WriteLine(s.Name);
                    return(s.Read());
                }).ToArray();
            }).Start();

            StaticTestSensors.Barrier.SignalAndWait();

            DiagnosticSensor.Register(SensorNameTester);
            DiagnosticSensor.Remove(MethodBase.GetCurrentMethod().Name);
        }
예제 #25
0
        public void Authorization_can_be_denied_for_specific_sensors()
        {
            var configuration = new HttpConfiguration
            {
                IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always
            }.MapSensorRoutes(ctx =>
            {
                var name = (string)ctx.ControllerContext.RouteData.Values["name"];
                return(!string.Equals(name, sensorName, StringComparison.OrdinalIgnoreCase));
            });
            var apiClient = new HttpClient(new HttpServer(configuration));

            DiagnosticSensor.Register(() => "hello", sensorName);

            apiClient.GetAsync("http://blammo.com/sensors/" + sensorName)
            .Result
            .ShouldFailWith(HttpStatusCode.Forbidden);
            apiClient.GetAsync("http://blammo.com/sensors/application")
            .Result
            .ShouldSucceed();
        }
예제 #26
0
        public void Cyclical_references_in_object_graphs_do_not_cause_serialization_errors()
        {
            DiagnosticSensor.Register(() =>
            {
                var parent = new Node();
                parent.ChildNodes.Add(new Node
                {
                    ChildNodes = new List <Node> {
                        parent
                    }
                });
                return(parent);
            }, sensorName);

            apiClient.GetAsync("http://blammo.com/sensors/").Result
            .StatusCode
            .Should()
            .Be(HttpStatusCode.OK);
            apiClient.GetAsync("http://blammo.com/sensors/" + sensorName).Result
            .StatusCode
            .Should()
            .Be(HttpStatusCode.OK);
        }
예제 #27
0
 public void Sensor_names_can_be_specified_using_DisplayNameAttribute()
 {
     DiagnosticSensor.KnownSensors()
     .Count(s => s.Name == "custom-name")
     .Should().Be(1);
 }
예제 #28
0
        public void Sensors_can_be_queried_based_on_return_type()
        {
            var sensors = DiagnosticSensor.KnownSensors().Where(s => s.ReturnType == typeof(FileInfo));

            Assert.That(sensors.Count(), Is.EqualTo(1));
        }
예제 #29
0
        public void Sensor_info_can_be_queried_based_on_sensor_declaring_type()
        {
            var sensors = DiagnosticSensor.KnownSensors().Where(s => s.DeclaringType == typeof(TestSensors));

            Assert.That(sensors.Count(), Is.AtLeast(2));
        }
예제 #30
0
        public void Sensor_methods_can_be_instance_methods()
        {
            var sensors = DiagnosticSensor.KnownSensors().Where(s => s.DeclaringType == typeof(TestSensors));

            Assert.That(sensors.Count(), Is.AtLeast(1));
        }