示例#1
0
        private void NotifyTrafficWatch(string resourceName, TrafficWatchNotification trafficWatchNotification)
        {
            object notificationMessage = new
            {
                Type  = "LogNotification",
                Value = trafficWatchNotification
            };

            if (serverHttpTrace.Count > 0)
            {
                foreach (var eventsTransport in serverHttpTrace)
                {
                    eventsTransport.SendAsync(notificationMessage);
                }
            }

            if (resourceHttpTraces.Count > 0)
            {
                ConcurrentSet <IEventsTransport> resourceEventTransports;

                if (!resourceHttpTraces.TryGetValue(resourceName, out resourceEventTransports) || resourceEventTransports.Count == 0)
                {
                    return;
                }

                foreach (var eventTransport in resourceEventTransports)
                {
                    eventTransport.SendAsync(notificationMessage);
                }
            }
        }
        private ArraySegment <byte> ToByteArraySegment(TrafficWatchNotification notification)
        {
            var json = new DynamicJsonValue
            {
                ["TimeStamp"]           = notification.TimeStamp,
                ["RequestId"]           = notification.RequestId,
                ["HttpMethod"]          = notification.HttpMethod,
                ["ElapsedMilliseconds"] = notification.ElapsedMilliseconds,
                ["ResponseStatusCode"]  = notification.ResponseStatusCode,
                ["RequestUri"]          = notification.RequestUri,
                ["AbsoluteUri"]         = notification.AbsoluteUri,
                ["TenantName"]          = notification.TenantName,
                ["CustomInfo"]          = notification.CustomInfo,
                ["InnerRequestsCount"]  = notification.InnerRequestsCount,
                //["QueryTimings"] = notification.QueryTimings // TODO :: implement this
            };

            _bufferStream.SetLength(0);
            JsonOperationContext context;

            using (_jsonContextPool.AllocateOperationContext(out context))
                using (var writer = new BlittableJsonTextWriter(context, _bufferStream))
                {
                    context.Write(writer, json);
                    writer.Flush();

                    ArraySegment <byte> bytes;
                    _bufferStream.TryGetBuffer(out bytes);
                    return(bytes);
                }
        }
        public static void DispatchMessage(TrafficWatchNotification trafficWatchData)
        {
            foreach (var connection in ServerHttpTrace)
            {
                if (connection.IsAlive == false)
                {
                    ServerHttpTrace.TryRemove(connection);
                    continue;
                }

                if (connection.TenantSpecific != null)
                {
                    if (string.Equals(connection.TenantSpecific, trafficWatchData.TenantName, StringComparison.OrdinalIgnoreCase) == false)
                    {
                        continue;
                    }
                }
                connection.EnqueMsg(trafficWatchData);
            }
        }
示例#4
0
        private async Task RequestHandler(HttpContext context)
        {
            try
            {
                context.Response.StatusCode = 200;
                var sp     = Stopwatch.StartNew();
                var tenant = await _router.HandlePath(context, context.Request.Method, context.Request.Path.Value);

                sp.Stop();

                if (_logger.IsInfoEnabled)
                {
                    _logger.Info($"{context.Request.Method} {context.Request.Path.Value}?{context.Request.QueryString.Value} - {context.Response.StatusCode} - {sp.ElapsedMilliseconds:#,#;;0} ms");
                }

                if (TrafficWatchManager.HasRegisteredClients)
                {
                    var requestId = Interlocked.Increment(ref _requestId);

                    var twn = new TrafficWatchNotification
                    {
                        TimeStamp           = DateTime.UtcNow,
                        RequestId           = requestId,                       // counted only for traffic watch
                        HttpMethod          = context.Request.Method ?? "N/A", // N/A ?
                        ElapsedMilliseconds = sp.ElapsedMilliseconds,
                        ResponseStatusCode  = context.Response.StatusCode,
                        RequestUri          = context.Request.GetEncodedUrl(),
                        AbsoluteUri         = $@"{context.Request.Scheme}://{context.Request.Host}",
                        TenantName          = tenant ?? "N/A",
                        CustomInfo          = "",   // TODO: Implement
                        InnerRequestsCount  = 0,    // TODO: Implement
                        QueryTimings        = null, // TODO: Implement
                    };

                    TrafficWatchManager.DispatchMessage(twn);
                }
            }
            catch (Exception e)
            {
                if (context.RequestAborted.IsCancellationRequested)
                {
                    return;
                }
                //TODO: special handling for argument exception (400 bad request)
                //TODO: database not found (503)
                //TODO: operaton cancelled (timeout)
                //TODO: Invalid data exception 422


                //TODO: Proper json output, not like this
                var response = context.Response;

                var documentConflictException = e as DocumentConflictException;
                if (response.HasStarted == false)
                {
                    if (documentConflictException != null)
                    {
                        response.StatusCode = 409;
                    }
                    else if (response.StatusCode < 400)
                    {
                        response.StatusCode = 500;
                    }
                }


                JsonOperationContext ctx;
                using (_server.ServerStore.ContextPool.AllocateOperationContext(out ctx))
                {
                    var djv = new DynamicJsonValue
                    {
                        ["Url"]     = $"{context.Request.Path}?{context.Request.QueryString}",
                        ["Type"]    = e.GetType().FullName,
                        ["Message"] = e.Message
                    };

                    string errorString;

                    try
                    {
                        errorString = e.ToAsyncString();
                    }
                    catch (Exception)
                    {
                        errorString = e.ToString();
                    }

                    djv["Error"] = errorString;

                    var indexCompilationException = e as IndexCompilationException;
                    if (indexCompilationException != null)
                    {
                        djv[nameof(IndexCompilationException.IndexDefinitionProperty)] =
                            indexCompilationException.IndexDefinitionProperty;
                        djv[nameof(IndexCompilationException.ProblematicText)] =
                            indexCompilationException.ProblematicText;
                    }

                    if (documentConflictException != null)
                    {
                        djv["ConflictInfo"] = ReplicationUtils.GetJsonForConflicts(
                            documentConflictException.DocId,
                            documentConflictException.Conflicts);
                    }

                    using (var writer = new BlittableJsonTextWriter(ctx, response.Body))
                    {
                        var json = ctx.ReadObject(djv, "exception");
                        writer.WriteObject(json);
                    }
                }
            }
        }
示例#5
0
        /// <summary>
        /// Connects to raven traffic event source and registers all the requests to the file defined in the config
        /// </summary>
        /// <param name="config">configuration conatining the connection, the file to write to, etc.</param>
        /// <param name="store">the store to work with</param>
        private async Task RecordRequests(TrafficToolConfiguration config, IDocumentStore store)
        {
            var id = Guid.NewGuid().ToString();

            using (var client = new RavenClientWebSocket())
            {
                var url = store.Url + "/traffic-watch/websockets";
                var uri = new Uri(url.ToWebSocketPath());

                await client.ConnectAsync(uri, CancellationToken.None)
                .ConfigureAwait(false);


                // record traffic no more then 7 days
                var day     = 24 * 60 * 60;
                var timeout = (int)config.Timeout.TotalMilliseconds / 1000;
                timeout = Math.Min(timeout, 7 * day);
                if (timeout <= 0)
                {
                    timeout = 7 * day;
                }

                try
                {
                    string resourceName   = config.ResourceName ?? "N/A";
                    var    connectMessage = new DynamicJsonValue
                    {
                        ["Id"]           = id,
                        ["ResourceName"] = resourceName,
                        ["Timeout"]      = timeout
                    };

                    var stream = new MemoryStream();

                    JsonOperationContext context;
                    using (_jsonContextPool.AllocateOperationContext(out context))
                        using (var writer = new BlittableJsonTextWriter(context, stream))
                        {
                            context.Write(writer, connectMessage);
                            writer.Flush();

                            ArraySegment <byte> bytes;
                            stream.TryGetBuffer(out bytes);
                            await client.SendAsync(bytes, WebSocketMessageType.Text, true, CancellationToken.None)
                            .ConfigureAwait(false);
                        }

                    var requestsCounter = 0;
                    using (var fileStream = File.Create(config.RecordFilePath))
                    {
                        Stream finalStream = fileStream;
                        if (config.IsCompressed)
                        {
                            finalStream = new GZipStream(fileStream, CompressionMode.Compress, leaveOpen: true);
                        }

                        using (var streamWriter = new StreamWriter(finalStream))
                        {
                            var jsonWriter = new JsonTextWriter(streamWriter)
                            {
                                Formatting = Formatting.Indented
                            };
                            jsonWriter.WriteStartArray();
                            var sp = Stopwatch.StartNew();

                            while (true)
                            {
                                using (var reader = await Receive(client, context))
                                {
                                    if (reader == null)
                                    {
                                        // server asked to close connection
                                        break;
                                    }

                                    string type;
                                    if (reader.TryGet("Type", out type))
                                    {
                                        if (type.Equals("Heartbeat"))
                                        {
                                            continue;
                                        }
                                    }

                                    string error;
                                    if (reader.TryGet("Error", out error))
                                    {
                                        throw new InvalidOperationException("Server returned error: " + error);
                                    }

                                    var notification = new TrafficWatchNotification();
                                    notification.TimeStamp           = GetDateTimeFromJson(reader, "TimeStamp");
                                    notification.RequestId           = GetIntFromJson(reader, "RequestId");
                                    notification.HttpMethod          = GetStringFromJson(reader, "HttpMethod");
                                    notification.ElapsedMilliseconds = GetIntFromJson(reader, "ElapsedMilliseconds");
                                    notification.ResponseStatusCode  = GetIntFromJson(reader, "ResponseStatusCode");
                                    notification.TenantName          = GetStringFromJson(reader, "TenantName");
                                    notification.CustomInfo          = GetStringFromJson(reader, "CustomInfo");
                                    notification.InnerRequestsCount  = GetIntFromJson(reader, "InnerRequestsCount");
                                    // notification.QueryTimings = GetRavenJObjectFromJson(reader, "QueryTimings"); // TODO (TrafficWatch) : Handle this both server and client sides

                                    if (config.PrintOutput)
                                    {
                                        Console.Write("\rRequest #{0} Stored...\t\t ", ++requestsCounter);
                                    }

                                    var jobj = RavenJObject.FromObject(notification);
                                    jobj.WriteTo(jsonWriter);

                                    if (sp.ElapsedMilliseconds > 5000)
                                    {
                                        streamWriter.Flush();
                                        sp.Restart();
                                    }
                                }
                            }
                            jsonWriter.WriteEndArray();
                            streamWriter.Flush();
                            if (config.IsCompressed)
                            {
                                finalStream.Dispose();
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("\r\n\nError while reading messages from server : " + ex);
                }
                finally
                {
                    Console.WriteLine("\r\n\nClosing connection to server...`");
                    try
                    {
                        await
                        client.CloseAsync(WebSocketCloseStatus.NormalClosure, "CLOSE_NORMAL", CancellationToken.None)
                        .ConfigureAwait(false);
                    }
                    catch
                    {
                        // ignored
                    }
                }
            }
        }
 public void EnqueMsg(TrafficWatchNotification msg)
 {
     _msgs.Enqueue(msg);
     _manualResetEvent.Set();
 }