Skip to content
This repository has been archived by the owner on Aug 30, 2023. It is now read-only.

Commit

Permalink
Merge pull request #182 from opcon/feature-user-feedback
Browse files Browse the repository at this point in the history
Feature:  Submit User Feedback for an Event
  • Loading branch information
asbjornu authored Nov 3, 2017
2 parents 64630f8 + 84178d4 commit 305a19b
Show file tree
Hide file tree
Showing 7 changed files with 252 additions and 9 deletions.
29 changes: 29 additions & 0 deletions src/app/SharpRaven/Data/Requester.Net45.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,35 @@ public async Task<string> RequestAsync()
}
}
}

/// <summary>
/// Sends the user feedback asynchronously to sentry
/// </summary>
/// <returns>An empty string if succesful, otherwise the server response</returns>
public async Task<string> SendFeedbackAsync()
{
using (var s = await this.webRequest.GetRequestStreamAsync())
{
using (var sw = new StreamWriter(s))
{
await sw.WriteAsync(feedback.ToString());
}
}
using (var wr = (HttpWebResponse)await this.webRequest.GetResponseAsync())
{
using (var responseStream = wr.GetResponseStream())
{
if (responseStream == null)
return null;

using (var sr = new StreamReader(responseStream))
{
var response = await sr.ReadToEndAsync();
return response;
}
}
}
}
}
}

Expand Down
79 changes: 70 additions & 9 deletions src/app/SharpRaven/Data/Requester.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ public partial class Requester
{
private readonly RequestData data;
private readonly JsonPacket packet;
private readonly SentryUserFeedback feedback;
private readonly RavenClient ravenClient;
private readonly HttpWebRequest webRequest;


/// <summary>
/// Initializes a new instance of the <see cref="Requester"/> class.
/// </summary>
Expand All @@ -70,24 +70,57 @@ internal Requester(JsonPacket packet, RavenClient ravenClient)
this.packet = ravenClient.PreparePacket(packet);
this.data = new RequestData(this);

this.webRequest = (HttpWebRequest)System.Net.WebRequest.Create(ravenClient.CurrentDsn.SentryUri);
this.webRequest.Timeout = (int)ravenClient.Timeout.TotalMilliseconds;
this.webRequest.ReadWriteTimeout = (int)ravenClient.Timeout.TotalMilliseconds;
this.webRequest.Method = "POST";
this.webRequest.Accept = "application/json";
this.webRequest.Headers.Add("X-Sentry-Auth", PacketBuilder.CreateAuthenticationHeader(ravenClient.CurrentDsn));
this.webRequest.UserAgent = PacketBuilder.UserAgent;
this.webRequest = CreateWebRequest(ravenClient.CurrentDsn.SentryUri);

if (ravenClient.Compression)
{
this.webRequest.Headers.Add(HttpRequestHeader.ContentEncoding, "gzip");
this.webRequest.AutomaticDecompression = DecompressionMethods.Deflate;
this.webRequest.ContentType = "application/octet-stream";
}

else
this.webRequest.ContentType = "application/json; charset=utf-8";

}

/// <summary>
/// Initializes a new instance of the <see cref="Requester"/> class.
/// </summary>
/// <param name="feedback">The <see cref="SentryUserFeedback"/> to initialize with.</param>
/// <param name="ravenClient">The <see cref="RavenClient"/> to initialize with.</param>
internal Requester(SentryUserFeedback feedback, RavenClient ravenClient)
{
if (feedback == null)
throw new ArgumentNullException("feedback");

if (ravenClient == null)
throw new ArgumentNullException("ravenClient");

this.ravenClient = ravenClient;
this.feedback = feedback;

var feedbackString = string.Format("{0}?dsn={1}&{2}",
ravenClient.CurrentDsn.FeedbackUri,
ravenClient.CurrentDsn.Uri,
feedback.ToString());
this.webRequest = CreateWebRequest(new Uri(feedbackString));
this.webRequest.Referer = ravenClient.CurrentDsn.Uri.DnsSafeHost;

this.webRequest.ContentType = "application/x-www-form-urlencoded";
}

internal HttpWebRequest CreateWebRequest(Uri uri)
{
var request = (HttpWebRequest)System.Net.WebRequest.Create(uri);
request.Timeout = (int)this.ravenClient.Timeout.TotalMilliseconds;
request.ReadWriteTimeout = (int)this.ravenClient.Timeout.TotalMilliseconds;
request.Method = "POST";
request.Accept = "application/json";
request.Headers.Add("X-Sentry-Auth", PacketBuilder.CreateAuthenticationHeader(this.ravenClient.CurrentDsn));
request.UserAgent = PacketBuilder.UserAgent;
return request;
}

/// <summary>
/// Gets the <see cref="IRavenClient"/>.
Expand Down Expand Up @@ -121,7 +154,6 @@ public HttpWebRequest WebRequest
get { return this.webRequest; }
}


/// <summary>
/// Executes the HTTP request to Sentry.
/// </summary>
Expand Down Expand Up @@ -164,5 +196,34 @@ public string Request()
}
}
}

/// <summary>
/// Sends the user feedback to sentry
/// </summary>
/// <returns>An empty string if succesful, otherwise the server response</returns>
public string SendFeedback()
{
using (var s = this.webRequest.GetRequestStream())
{
using (var sw = new StreamWriter(s))
{
sw.Write(feedback.ToString());
}
}
using (var wr = (HttpWebResponse)this.webRequest.GetResponse())
{
using (var responseStream = wr.GetResponseStream())
{
if (responseStream == null)
return null;

using (var sr = new StreamReader(responseStream))
{
var response = sr.ReadToEnd();
return response;
}
}
}
}
}
}
92 changes: 92 additions & 0 deletions src/app/SharpRaven/Data/SentryUserFeedback.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#region License

// Copyright (c) 2014 The Sentry Team and individual contributors.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are permitted
// provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of
// conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// 3. Neither the name of the Sentry nor the names of its contributors may be used to
// endorse or promote products derived from this software without specific prior written
// permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System.Text;

#endregion

using System;
using System.Collections.Generic;
using System.Net;
#if net35
using System.Web;
#endif

namespace SharpRaven.Data
{
/// <summary>
/// Represents the UserFeedback that is transmitted to Sentry
/// </summary>
public class SentryUserFeedback
{
/// <summary>
/// The name associated with this feedback
/// </summary>
public string Name { get; set; }

/// <summary>
/// The email associated with this feedback
/// </summary>
public string Email { get; set; }

/// <summary>
/// The comments associated with this feedback
/// </summary>
public string Comments { get; set; }

/// <summary>
/// The event ID associated with this feedback
/// </summary>
public string EventID {get; set;}

/// <summary>
/// Returns the url request string for this user feedback
/// </summary>
/// <returns>A <see cref="System.String"/> that represents the url request string for this <see cref="SharpRaven.Data.SentryUserFeedback"/>.</returns>
public override string ToString()
{
return string.Format("eventId={0}&name={1}&email={2}&comments={3}",
#if net35
HttpUtility.UrlEncode(EventID),
HttpUtility.UrlEncode(Name),
HttpUtility.UrlEncode(Email),
HttpUtility.UrlEncode(Comments));
#elif net40
WebUtility.HtmlEncode(EventID),
WebUtility.HtmlEncode(Name),
WebUtility.HtmlEncode(Email),
WebUtility.HtmlEncode(Comments));
#else
WebUtility.UrlEncode(EventID),
WebUtility.UrlEncode(Name),
WebUtility.UrlEncode(Email),
WebUtility.UrlEncode(Comments));
#endif
}
}
}

15 changes: 15 additions & 0 deletions src/app/SharpRaven/Dsn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public class Dsn
private readonly string projectID;
private readonly string publicKey;
private readonly Uri sentryUri;
private readonly Uri feedbackUri;
private readonly Uri uri;


Expand All @@ -71,6 +72,12 @@ public Dsn(string dsn)
Path,
ProjectID);
this.sentryUri = new Uri(sentryUriString);
var feedbackUriString = String.Format("{0}://{1}:{2}{3}/api/embed/error-page/",
this.uri.Scheme,
this.uri.DnsSafeHost,
Port,
Path);
this.feedbackUri = new Uri(feedbackUriString);
}
catch (Exception exception)
{
Expand Down Expand Up @@ -127,6 +134,14 @@ public Uri SentryUri
get { return this.sentryUri; }
}

/// <summary>
/// The Sentry Uri for sending user feedback
/// </summary>
public Uri FeedbackUri
{
get { return this.feedbackUri; }
}

/// <summary>
/// Absolute Dsn Uri
/// </summary>
Expand Down
22 changes: 22 additions & 0 deletions src/app/SharpRaven/RavenClient.Net45.cs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,28 @@ protected virtual async Task<string> SendAsync(JsonPacket packet)
{
return HandleException(exception, requester);
}
}

/// <summary>Sends the specified user feedback to Sentry</summary>
/// <returns>An empty string if succesful, otherwise the server response</returns>
/// <param name="feedback">The user feedback to send</param>
public async Task<string> SendUserFeedbackAsync(SentryUserFeedback feedback)
{
Requester requester = null;

try
{
requester = new Requester(feedback, this);

if (BeforeSend != null)
requester = BeforeSend(requester);

return await requester.SendFeedbackAsync();
}
catch (Exception exception)
{
return HandleException(exception, requester);
}
}
}
}
Expand Down
23 changes: 23 additions & 0 deletions src/app/SharpRaven/RavenClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ public string Capture(SentryEvent @event)
}



/// <summary>
/// Captures the event.
/// </summary>
Expand Down Expand Up @@ -367,6 +368,28 @@ protected virtual string Send(JsonPacket packet)
}
}

/// <summary>Sends the specified user feedback to Sentry</summary>
/// <returns>An empty string if succesful, otherwise the server response</returns>
/// <param name="feedback">The user feedback to send</param>
public string SendUserFeedback(SentryUserFeedback feedback)
{
Requester requester = null;

try
{
requester = new Requester(feedback, this);

if (BeforeSend != null)
requester = BeforeSend(requester);

return requester.SendFeedback();
}
catch (Exception exception)
{
return HandleException(exception, requester);
}
}


private string HandleException(Exception exception, Requester requester)
{
Expand Down
1 change: 1 addition & 0 deletions src/app/SharpRaven/SharpRaven.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@
<Compile Include="Data\SentryRequestFactory.cs" />
<Compile Include="Data\SentryStacktrace.cs" />
<Compile Include="Data\SentryUser.cs" />
<Compile Include="Data\SentryUserFeedback.cs" />
<Compile Include="Dsn.cs" />
<Compile Include="Data\JsonPacket.cs" />
<Compile Include="IRavenClient.cs" />
Expand Down

0 comments on commit 305a19b

Please sign in to comment.