diff --git a/EventGenerator/EventGenerator.sln b/EventGenerator/EventGenerator.sln new file mode 100644 index 0000000..ff3fae9 --- /dev/null +++ b/EventGenerator/EventGenerator.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26730.16 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventGenerator", "EventGenerator\EventGenerator.csproj", "{C3DBE575-343E-4C6D-9E89-4A4032A81A68}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C3DBE575-343E-4C6D-9E89-4A4032A81A68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C3DBE575-343E-4C6D-9E89-4A4032A81A68}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C3DBE575-343E-4C6D-9E89-4A4032A81A68}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C3DBE575-343E-4C6D-9E89-4A4032A81A68}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {6D315680-7A26-4A3E-A536-87E729253BD8} + EndGlobalSection +EndGlobal diff --git a/EventGenerator/EventGenerator/BusinessLogic/EventGenerationManager.cs b/EventGenerator/EventGenerator/BusinessLogic/EventGenerationManager.cs new file mode 100644 index 0000000..0f30eb4 --- /dev/null +++ b/EventGenerator/EventGenerator/BusinessLogic/EventGenerationManager.cs @@ -0,0 +1,25 @@ +using EventGenerator.Models; + +namespace EventGenerator.BusinessLogic +{ + public class EventGenerationManager : IEventGenerationManager + { + private readonly IEventGeneratorRegistry _generatorRegistry; + + public EventGenerationManager(IEventGeneratorRegistry generatorRegistry) + { + _generatorRegistry = generatorRegistry; + } + + public bool Send(EventType argsEventType, int argsCount) + { + var generator = _generatorRegistry.Get(argsEventType); + if (generator != null) + { + generator.Generate(argsCount); + return true; + } + return false; + } + } +} \ No newline at end of file diff --git a/EventGenerator/EventGenerator/BusinessLogic/EventGeneratorRegistry.cs b/EventGenerator/EventGenerator/BusinessLogic/EventGeneratorRegistry.cs new file mode 100644 index 0000000..0f9956b --- /dev/null +++ b/EventGenerator/EventGenerator/BusinessLogic/EventGeneratorRegistry.cs @@ -0,0 +1,17 @@ +using System.Collections.Concurrent; +using EventGenerator.Models; + +namespace EventGenerator.BusinessLogic +{ + public class EventGeneratorRegistry : IEventGeneratorRegistry + { + private readonly ConcurrentDictionary _registry; + + public EventGeneratorRegistry() => _registry = new ConcurrentDictionary(); + + public void Add(EventType eventType, IEventGenerator generator) => _registry[eventType] = generator; + + public IEventGenerator Get(EventType eventType) => + _registry.TryGetValue(eventType, out var result) ? result : null; + } +} \ No newline at end of file diff --git a/EventGenerator/EventGenerator/BusinessLogic/IEventGenerationManager.cs b/EventGenerator/EventGenerator/BusinessLogic/IEventGenerationManager.cs new file mode 100644 index 0000000..8f5da56 --- /dev/null +++ b/EventGenerator/EventGenerator/BusinessLogic/IEventGenerationManager.cs @@ -0,0 +1,9 @@ +using EventGenerator.Models; + +namespace EventGenerator.BusinessLogic +{ + public interface IEventGenerationManager + { + bool Send(EventType argsEventType, int argsCount); + } +} \ No newline at end of file diff --git a/EventGenerator/EventGenerator/BusinessLogic/IEventGenerator.cs b/EventGenerator/EventGenerator/BusinessLogic/IEventGenerator.cs new file mode 100644 index 0000000..9bd5d42 --- /dev/null +++ b/EventGenerator/EventGenerator/BusinessLogic/IEventGenerator.cs @@ -0,0 +1,7 @@ +namespace EventGenerator.BusinessLogic +{ + public interface IEventGenerator + { + void Generate(int count); + } +} \ No newline at end of file diff --git a/EventGenerator/EventGenerator/BusinessLogic/IEventGeneratorRegistry.cs b/EventGenerator/EventGenerator/BusinessLogic/IEventGeneratorRegistry.cs new file mode 100644 index 0000000..f3d3618 --- /dev/null +++ b/EventGenerator/EventGenerator/BusinessLogic/IEventGeneratorRegistry.cs @@ -0,0 +1,10 @@ +using EventGenerator.Models; + +namespace EventGenerator.BusinessLogic +{ + public interface IEventGeneratorRegistry + { + void Add(EventType eventType, IEventGenerator generator); + IEventGenerator Get(EventType eventType); + } +} \ No newline at end of file diff --git a/EventGenerator/EventGenerator/BusinessLogic/LogEventGenerator.cs b/EventGenerator/EventGenerator/BusinessLogic/LogEventGenerator.cs new file mode 100644 index 0000000..b6fc4fd --- /dev/null +++ b/EventGenerator/EventGenerator/BusinessLogic/LogEventGenerator.cs @@ -0,0 +1,20 @@ +using Vostok.Logging; + +namespace EventGenerator.BusinessLogic +{ + public class LogEventGenerator : IEventGenerator + { + private readonly ILog _log; + + public LogEventGenerator(ILog log) + { + _log = log; + } + + public void Generate(int count) + { + for (int i = 0; i < count; i++) + _log.Info("Generate info log event"); + } + } +} \ No newline at end of file diff --git a/EventGenerator/EventGenerator/BusinessLogic/MetricEventGenerator.cs b/EventGenerator/EventGenerator/BusinessLogic/MetricEventGenerator.cs new file mode 100644 index 0000000..1013244 --- /dev/null +++ b/EventGenerator/EventGenerator/BusinessLogic/MetricEventGenerator.cs @@ -0,0 +1,22 @@ +using System; +using Vostok.Metrics; +using Vostok.Metrics.Meters; + +namespace EventGenerator.BusinessLogic +{ + public class MetricEventGenerator : IEventGenerator + { + private readonly ICounter _counter; + + public MetricEventGenerator(IMetricScope scope) + { + _counter = scope.Counter(TimeSpan.FromMilliseconds(100), "generated"); + } + + public void Generate(int count) + { + for (var i = 0; i < count; i++) + _counter.Add(); + } + } +} \ No newline at end of file diff --git a/EventGenerator/EventGenerator/BusinessLogic/TraceEventGenerator.cs b/EventGenerator/EventGenerator/BusinessLogic/TraceEventGenerator.cs new file mode 100644 index 0000000..713c8b0 --- /dev/null +++ b/EventGenerator/EventGenerator/BusinessLogic/TraceEventGenerator.cs @@ -0,0 +1,25 @@ +using Vostok.Tracing; + +namespace EventGenerator.BusinessLogic +{ + public class TraceEventGenerator : IEventGenerator + { + public void Generate(int count) + { + for (int i = 0; i < count; i++) + { + using (var spanBuilder = Trace.BeginSpan()) + { + spanBuilder.SetAnnotation(TracingAnnotationNames.Operation, "Generate Trace"); + spanBuilder.SetAnnotation(TracingAnnotationNames.Kind, "loadtest"); + spanBuilder.SetAnnotation(TracingAnnotationNames.Service, "event-generator"); + spanBuilder.SetAnnotation(TracingAnnotationNames.Host, "localhost"); + spanBuilder.SetAnnotation(TracingAnnotationNames.HttpUrl, "send"); + spanBuilder.SetAnnotation(TracingAnnotationNames.HttpRequestContentLength, 1024); + spanBuilder.SetAnnotation(TracingAnnotationNames.HttpResponseContentLength, 2048); + spanBuilder.SetAnnotation(TracingAnnotationNames.HttpCode, 200); + } + } + } + } +} \ No newline at end of file diff --git a/EventGenerator/EventGenerator/Controllers/GenerateController.cs b/EventGenerator/EventGenerator/Controllers/GenerateController.cs new file mode 100644 index 0000000..db295eb --- /dev/null +++ b/EventGenerator/EventGenerator/Controllers/GenerateController.cs @@ -0,0 +1,28 @@ +using EventGenerator.BusinessLogic; +using EventGenerator.Models; +using Microsoft.AspNetCore.Mvc; + +namespace EventGenerator.Controllers +{ + [Route("/[controller]")] + public class GenerateController : Controller + { + private readonly IEventGenerationManager _manager; + + public GenerateController(IEventGenerationManager manager) + { + _manager = manager; + } + + [HttpPost] + public IActionResult Index([FromBody] GenerateEventsArgs args) + { + if (ModelState.IsValid) + { + var ok = _manager.Send(args.EventType, args.Count); + return ok ? Ok() : StatusCode(500); + } + return BadRequest(ModelState); + } + } +} \ No newline at end of file diff --git a/EventGenerator/EventGenerator/EventGenerator.csproj b/EventGenerator/EventGenerator/EventGenerator.csproj new file mode 100644 index 0000000..f274285 --- /dev/null +++ b/EventGenerator/EventGenerator/EventGenerator.csproj @@ -0,0 +1,26 @@ + + + + netcoreapp2.0 + + + + + + + + + + + + + + + + + + PreserveNewest + + + + diff --git a/EventGenerator/EventGenerator/Models/EventType.cs b/EventGenerator/EventGenerator/Models/EventType.cs new file mode 100644 index 0000000..580ea68 --- /dev/null +++ b/EventGenerator/EventGenerator/Models/EventType.cs @@ -0,0 +1,9 @@ +namespace EventGenerator.Models +{ + public enum EventType + { + Logs, + Trace, + Metric + } +} \ No newline at end of file diff --git a/EventGenerator/EventGenerator/Models/GenerateEventsArgs.cs b/EventGenerator/EventGenerator/Models/GenerateEventsArgs.cs new file mode 100644 index 0000000..a3bce11 --- /dev/null +++ b/EventGenerator/EventGenerator/Models/GenerateEventsArgs.cs @@ -0,0 +1,14 @@ +using System.ComponentModel; +using System.ComponentModel.DataAnnotations; + +namespace EventGenerator.Models +{ + public class GenerateEventsArgs + { + [Required] + public EventType EventType { get; set; } + + [Range(1, 10000)] + public int Count { get; set; } = 1; + } +} \ No newline at end of file diff --git a/EventGenerator/EventGenerator/Program.cs b/EventGenerator/EventGenerator/Program.cs new file mode 100644 index 0000000..ae17a22 --- /dev/null +++ b/EventGenerator/EventGenerator/Program.cs @@ -0,0 +1,52 @@ +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Serilog; +using Vostok.Instrumentation.AspNetCore; +using Vostok.Logging; +using Vostok.Logging.Serilog; + +namespace EventGenerator +{ + public class Program + { + public static void Main(string[] args) + { + BuildWebHost(args).Run(); + } + + public static IWebHost BuildWebHost(string[] args) => + WebHost.CreateDefaultBuilder(args) + .ConfigureAppConfiguration((hostingContext, config) => + { + config.AddJsonFile("appsettings.json", false, true); + }) + .UseUrls("http://*:5000") + .ConfigureLogging(ConfigureLogging) + .ConfigureAirlock() + .ConfigureVostokMetrics() + .ConfigureVostokTracing() + .UseStartup() + .Build(); + + private static void ConfigureLogging(WebHostBuilderContext context, ILoggingBuilder builder) + { + var loggingSection = context.Configuration.GetSection("logging"); + var rollingFileSection = loggingSection.GetSection("rollingFile"); + var rollingFilePathFormat = rollingFileSection.GetValue("pathFormat"); + var service = context.Configuration.GetValue("service"); + var template = "{Timestamp:HH:mm:ss.fff} {Level} {Message:l} {Exception}{NewLine}{Properties}{NewLine}"; + + Log.Logger = new LoggerConfiguration() + .Enrich.WithProperty("Service", service) + .WriteTo.Async(x => x.RollingFile(rollingFilePathFormat, outputTemplate: template)) + .CreateLogger(); + var log = new SerilogLog(Log.Logger).WithFlowContext(); + + builder.AddVostok(log); + builder.Services.AddSingleton(log); + } + } +} diff --git a/EventGenerator/EventGenerator/Properties/launchSettings.json b/EventGenerator/EventGenerator/Properties/launchSettings.json new file mode 100644 index 0000000..bbbd7e5 --- /dev/null +++ b/EventGenerator/EventGenerator/Properties/launchSettings.json @@ -0,0 +1,29 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:58226/", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "api/values", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "EventGenerator": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "api/values", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:58227/" + } + } +} diff --git a/tank/README.md b/EventGenerator/EventGenerator/README.md similarity index 68% rename from tank/README.md rename to EventGenerator/EventGenerator/README.md index 0694cc7..cae0b9c 100644 --- a/tank/README.md +++ b/EventGenerator/EventGenerator/README.md @@ -1,9 +1,13 @@ +0. Запустить EventGenerator: + + > dotnet EventGenerator.dll + 1. Создать рабочий каталог для танка и перейти в него. В этом каталоге танк оставит логи > md tank > cd tank -2. Скопировать в рабочий каталог конфиг танка vostok.yaml. +2. Скопировать в рабочий каталог конфиг танка tank-vostok.yaml. 3. Скопировать в рабочий каталог нужный файл с патронами в файл ammo: @@ -11,7 +15,6 @@ 4. Запустить танк: - docker run -v $(pwd):/var/loadtest -v $HOME/.ssh:/root/.ssh --net host -it direvius/yandex-tank -c vostok.yaml - -5. Логи танка будут в каталоге logs. + docker run -v $(pwd):/var/loadtest -v $HOME/.ssh:/root/.ssh --net host -it direvius/yandex-tank -c tank-vostok.yaml +5. Логи танка будут в каталоге logs. \ No newline at end of file diff --git a/EventGenerator/EventGenerator/Startup.cs b/EventGenerator/EventGenerator/Startup.cs new file mode 100644 index 0000000..56ab60a --- /dev/null +++ b/EventGenerator/EventGenerator/Startup.cs @@ -0,0 +1,61 @@ +using EventGenerator.BusinessLogic; +using EventGenerator.Models; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Serilog; +using Vostok.Airlock; +using Vostok.Logging; +using Vostok.Logging.Serilog; +using Vostok.Metrics; + +namespace EventGenerator +{ + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + services.AddMvc(); + + var serviceProvider = services.BuildServiceProvider(); + var airlockClient = serviceProvider.GetService(); + var service = Configuration.GetValue("service"); + var project = Configuration.GetValue("project"); + var environment = Configuration.GetValue("environment"); + var routingKeyPrefix = RoutingKey.Create(project, environment, service, RoutingKey.LogsSuffix); + + var airlockLogger = new LoggerConfiguration() + .Enrich.WithProperty("Service", service) + .WriteTo.Airlock(airlockClient, routingKeyPrefix) + .CreateLogger(); + var log = new SerilogLog(airlockLogger).WithFlowContext(); + var rootMetricScope = serviceProvider.GetService(); + + var registry = new EventGeneratorRegistry(); + registry.Add(EventType.Logs, new LogEventGenerator(log)); + registry.Add(EventType.Trace, new TraceEventGenerator()); + registry.Add(EventType.Metric, new MetricEventGenerator(rootMetricScope)); + services.AddSingleton(new EventGenerationManager(registry)); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IHostingEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseMvc(); + } + } +} diff --git a/EventGenerator/EventGenerator/ammo-logs.txt b/EventGenerator/EventGenerator/ammo-logs.txt new file mode 100644 index 0000000..c090523 --- /dev/null +++ b/EventGenerator/EventGenerator/ammo-logs.txt @@ -0,0 +1,5 @@ +[Content-Type: application/json] +24 /generate +{eventType: 0, count: 1} +24 /generate +{eventType: 0, count: 1} diff --git a/EventGenerator/EventGenerator/ammo-metrics.txt b/EventGenerator/EventGenerator/ammo-metrics.txt new file mode 100644 index 0000000..ecc0abf --- /dev/null +++ b/EventGenerator/EventGenerator/ammo-metrics.txt @@ -0,0 +1,5 @@ +[Content-Type: application/json] +24 /generate +{eventType: 2, count: 1} +24 /generate +{eventType: 2, count: 1} diff --git a/EventGenerator/EventGenerator/ammo-mix.txt b/EventGenerator/EventGenerator/ammo-mix.txt new file mode 100644 index 0000000..575d86b --- /dev/null +++ b/EventGenerator/EventGenerator/ammo-mix.txt @@ -0,0 +1,7 @@ +[Content-Type: application/json] +24 /generate +{eventType: 0, count: 1} +24 /generate +{eventType: 1, count: 1} +24 /generate +{eventType: 1, count: 1} diff --git a/EventGenerator/EventGenerator/ammo-trace.txt b/EventGenerator/EventGenerator/ammo-trace.txt new file mode 100644 index 0000000..abc38c6 --- /dev/null +++ b/EventGenerator/EventGenerator/ammo-trace.txt @@ -0,0 +1,5 @@ +[Content-Type: application/json] +24 /generate +{eventType: 1, count: 1} +24 /generate +{eventType: 1, count: 1} diff --git a/EventGenerator/EventGenerator/appsettings.Development.json b/EventGenerator/EventGenerator/appsettings.Development.json new file mode 100644 index 0000000..fa8ce71 --- /dev/null +++ b/EventGenerator/EventGenerator/appsettings.Development.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "IncludeScopes": false, + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/EventGenerator/EventGenerator/appsettings.json b/EventGenerator/EventGenerator/appsettings.json new file mode 100644 index 0000000..a74d0ec --- /dev/null +++ b/EventGenerator/EventGenerator/appsettings.json @@ -0,0 +1,22 @@ +{ + "project": "Vostok.LoadTest", + "environment": "dev", + "service": "EventGenerator", + "airlock": { + "config": { + "apiKey": "UniversalApiKey", + "host": "http://localhost:6306", + "logFilePathFormat": "airlock-{Date}.log" + } + }, + "logging": { + "rollingFile": { + "pathFormat": "log-{Date}.log" + }, + "Console": { + "LogLevel": { + "Default": "Warning" + } + } + } +} diff --git a/tank/vostok.yaml b/EventGenerator/EventGenerator/tank-vostok.yaml similarity index 71% rename from tank/vostok.yaml rename to EventGenerator/EventGenerator/tank-vostok.yaml index 746e5c4..9439ca7 100644 --- a/tank/vostok.yaml +++ b/EventGenerator/EventGenerator/tank-vostok.yaml @@ -1,9 +1,9 @@ phantom: - address: localhost:8888 + address: localhost:5000 load_profile: load_type: rps schedule: line(1, 10, 10m) - ammo_type: phantom + ammo_type: uripost ammofile: ammo telegraf: enabled: false diff --git a/tank/ammo-logs.txt b/tank/ammo-logs.txt deleted file mode 100644 index c4e1d8f..0000000 Binary files a/tank/ammo-logs.txt and /dev/null differ