Skip to content

Commit af3e828

Browse files
committed
improve
1 parent a22fefe commit af3e828

8 files changed

Lines changed: 153 additions & 91 deletions

.github/workflows/deploy-nuget.yml

Lines changed: 49 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,66 @@
1-
name: Build and Deploy to Nuget
1+
name: Build and Deploy NuGet Package
22

33
on:
44
push:
5-
branches: [ main, dev ]
5+
branches:
6+
- main
7+
- dev
68

7-
env:
8-
NUGET_API_URL: https://api.nuget.org/v3/index.json
9+
workflow_dispatch:
10+
inputs:
11+
force:
12+
description: 'Force exec'
13+
type: boolean
14+
required: true
15+
default: false
916

1017
jobs:
11-
build:
18+
Detect:
1219
runs-on: ubuntu-latest
20+
outputs:
21+
app: ${{ steps.detect.outputs.app }}
1322
steps:
1423
- uses: actions/checkout@v3
1524
with:
1625
fetch-depth: 0
17-
- name: Setup .NET
18-
uses: actions/setup-dotnet@v1
19-
with:
20-
dotnet-version: 6.0.x
21-
- name: Restore dependencies
22-
run: dotnet restore
23-
- name: Build
24-
run: dotnet build --no-restore
25-
- name: Pack
26+
- name: Detect Change
27+
id: detect
2628
run: |
27-
BRANCH="${GITHUB_REF##*/}"
28-
COMMIT_SHORT_SHA=`git rev-parse --short ${GITHUB_SHA}`
29-
COMMIT_COUNT=`git rev-list --count HEAD`
30-
COMMIT_TIME=`git show -s --format=%ct HEAD`
31-
if [ "$BRANCH" = "main" ]; then
32-
dotnet pack --no-dependencies -c Release
33-
else
34-
dotnet pack --no-dependencies -c Debug --version-suffix ${BRANCH}.${COMMIT_TIME}+${COMMIT_SHORT_SHA}
29+
APP="${GITHUB_REPOSITORY#*/}"
30+
31+
PROJECT_PATH=`find . -type f -iname "*.csproj" | grep -Em1 "${APP}(.API)?.csproj" || true`
32+
33+
if [ ! -z "$PROJECT_PATH" ]; then
34+
APP=`basename "${PROJECT_PATH}" .csproj`
3535
fi
36-
- name: Find Package
37-
run: |
38-
mkdir -p ./packages
39-
find ** -type f -regex '.*\.s?nupkg' -exec mv {} ./packages/ \;
40-
- uses: actions/upload-artifact@v2
41-
with:
42-
name: packages
43-
path: ./packages
36+
37+
CHANGE_FILES=`git diff --no-commit-id --name-only HEAD^`
4438
45-
deploy:
39+
CHANGED=`echo "$CHANGE_FILES" | grep -Em 1 '.cs|.proto' || true`
40+
if [ -z "$CHANGED" ] && [ "${{ inputs.force }}" != true ]; then
41+
echo "No changes detected"
42+
43+
APP=""
44+
fi
45+
46+
echo "app=${APP}" >> $GITHUB_OUTPUT
47+
Build:
48+
needs: Detect
49+
if: needs.Detect.outputs.app != ''
4650
runs-on: ubuntu-latest
47-
needs: build
51+
outputs:
52+
artifact: ${{ steps.build.outputs.artifact }}
4853
steps:
49-
- uses: actions/download-artifact@v2
50-
with:
51-
name: packages
52-
- name: Setup .NET
53-
uses: actions/setup-dotnet@v1
54+
- id: build
55+
name: Build Package
56+
uses: netcorext/dotnet-build-package-action@dev
57+
Deploy:
58+
needs: Build
59+
runs-on: ubuntu-latest
60+
steps:
61+
- uses: netcorext/push-nuget-package-action@dev
62+
name: Push Package
5463
with:
55-
dotnet-version: 6.0.x
56-
- name: Push packages
57-
run: find ** -type f -regex '.*\.s?nupkg' -exec dotnet nuget push -s ${{ env.NUGET_API_URL }} -k ${{ secrets.NUGET_API_KEY }} --skip-duplicate {} \;
64+
artifact: ${{ needs.Build.outputs.artifact }}
65+
nuget-api-url: ${{ secrets.NUGET_API_URL }}
66+
nuget-api-key: ${{ secrets.NUGET_API_KEY }}

CustomLoggingOptions.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace Netcorext.Logging.HttpClientLogger;
2+
3+
public class CustomLoggingOptions
4+
{
5+
public bool LogRequestHeader { get; set; }
6+
public bool LogRequestBody { get; set; }
7+
public bool LogResponseHeader { get; set; }
8+
public bool LogResponseBody { get; set; }
9+
public long SlowRequestLoggingThreshold { get; set; } = 2 * 1000;
10+
}

Extensions/HttpClientBuilderExtension.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,23 @@ public static class HttpClientBuilderExtension
88
public static IHttpClientBuilder AddLoggingHttpMessage(this IHttpClientBuilder builder)
99
{
1010
builder.Services.RemoveAll<IHttpMessageHandlerBuilderFilter>();
11+
builder.Services.TryAddSingleton<CustomLoggingOptions>();
12+
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IHttpMessageHandlerBuilderFilter, CustomLoggingHttpMessageHandlerBuilderFilter>());
13+
14+
return builder;
15+
}
16+
17+
public static IHttpClientBuilder AddLoggingHttpMessage(this IHttpClientBuilder builder, Action<IServiceProvider, CustomLoggingOptions>? configure)
18+
{
19+
builder.Services.RemoveAll<IHttpMessageHandlerBuilderFilter>();
20+
builder.Services.TryAddSingleton<CustomLoggingOptions>(provider =>
21+
{
22+
var options = new CustomLoggingOptions();
23+
24+
configure?.Invoke(provider, options);
1125

26+
return options;
27+
});
1228
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IHttpMessageHandlerBuilderFilter, CustomLoggingHttpMessageHandlerBuilderFilter>());
1329

1430
return builder;

Filters/CustomLoggingHttpMessageHandlerBuilderFilter.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ namespace Netcorext.Logging.HttpClientLogger;
44

55
public class CustomLoggingHttpMessageHandlerBuilderFilter : IHttpMessageHandlerBuilderFilter
66
{
7+
private readonly CustomLoggingOptions _options;
78
private readonly ILoggerFactory _loggerFactory;
89

9-
public CustomLoggingHttpMessageHandlerBuilderFilter(ILoggerFactory loggerFactory)
10+
public CustomLoggingHttpMessageHandlerBuilderFilter(CustomLoggingOptions options, ILoggerFactory loggerFactory)
1011
{
12+
_options = options;
1113
_loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
1214
}
1315

@@ -31,11 +33,11 @@ public Action<HttpMessageHandlerBuilder> Configure(Action<HttpMessageHandlerBuil
3133
var innerLogger = _loggerFactory.CreateLogger($"System.Net.Http.HttpClient.{loggerName}.ClientHandler");
3234

3335
// The 'scope' handler goes first so it can surround everything.
34-
builder.AdditionalHandlers.Insert(0, new CustomLoggingScopeHttpMessageHandler(outerLogger));
36+
builder.AdditionalHandlers.Insert(0, new CustomLoggingScopeHttpMessageHandler(_options, outerLogger));
3537

3638
// We want this handler to be last so we can log details about the request after
3739
// service discovery and security happen.
38-
builder.AdditionalHandlers.Add(new CustomLoggingHttpMessageHandler(innerLogger));
40+
builder.AdditionalHandlers.Add(new CustomLoggingHttpMessageHandler(_options, innerLogger));
3941
};
4042
}
4143
}

Handlers/CustomLoggingHttpMessageHandler.cs

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ namespace Netcorext.Logging.HttpClientLogger;
55

66
public class CustomLoggingHttpMessageHandler : DelegatingHandler
77
{
8+
private readonly CustomLoggingOptions _options;
89
private readonly ILogger _logger;
910

10-
public CustomLoggingHttpMessageHandler(ILogger logger)
11+
public CustomLoggingHttpMessageHandler(CustomLoggingOptions options, ILogger logger)
1112
{
13+
_options = options;
1214
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
1315
}
1416

@@ -23,9 +25,9 @@ protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage
2325

2426
// Not using a scope here because we always expect this to be at the end of the pipeline, thus there's
2527
// not really anything to surround.
26-
Log.RequestStart(_logger, request);
28+
Log.RequestStart(_options, _logger, request);
2729
var response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
28-
Log.RequestEnd(_logger, response, stopwatch.GetElapsedTime());
30+
Log.RequestEnd(_options, _logger, response, stopwatch.GetElapsedTime());
2931

3032
return response;
3133
}
@@ -34,14 +36,14 @@ private static class Log
3436
{
3537
public static class EventIds
3638
{
37-
public static readonly EventId RequestStart = new EventId(100, "RequestStart");
38-
public static readonly EventId RequestEnd = new EventId(101, "RequestEnd");
39+
public static readonly EventId RequestStart = new(100, "RequestStart");
40+
public static readonly EventId RequestEnd = new(101, "RequestEnd");
3941

40-
public static readonly EventId RequestHeader = new EventId(102, "RequestHeader");
41-
public static readonly EventId ResponseHeader = new EventId(103, "ResponseHeader");
42+
public static readonly EventId RequestHeader = new(102, "RequestHeader");
43+
public static readonly EventId ResponseHeader = new(103, "ResponseHeader");
4244

43-
public static readonly EventId RequestContent = new EventId(104, "RequestContent");
44-
public static readonly EventId ResponseContent = new EventId(105, "ResponseContent");
45+
public static readonly EventId RequestContent = new(104, "RequestContent");
46+
public static readonly EventId ResponseContent = new(105, "ResponseContent");
4547
}
4648

4749
private static readonly Action<ILogger, HttpMethod, Uri, Exception> _requestStart = LoggerMessage.Define<HttpMethod, Uri>(
@@ -54,48 +56,58 @@ public static class EventIds
5456
EventIds.RequestEnd,
5557
"Received HTTP response after {ElapsedMilliseconds}ms - {StatusCode}");
5658

57-
public static void RequestStart(ILogger logger, HttpRequestMessage request)
59+
private static readonly Action<ILogger, double, HttpStatusCode, Exception> _requestEndTooSlow = LoggerMessage.Define<double, HttpStatusCode>(
60+
LogLevel.Warning,
61+
EventIds.RequestEnd,
62+
"Received HTTP response too slow, elapsed: {ElapsedMilliseconds}ms - {StatusCode}");
63+
64+
public static void RequestStart(CustomLoggingOptions options, ILogger logger, HttpRequestMessage request)
5865
{
5966
_requestStart(logger, request.Method, request.RequestUri, null);
6067

61-
if (logger.IsEnabled(LogLevel.Trace))
62-
{
68+
if (options.LogRequestHeader && logger.IsEnabled(LogLevel.Debug))
6369
logger.Log(
64-
LogLevel.Trace,
70+
LogLevel.Debug,
6571
EventIds.RequestHeader,
6672
new HttpHeadersLogValue(Kind.Request, request.Headers, request.Content?.Headers),
6773
null,
6874
(state, ex) => state.ToString());
6975

76+
if (options.LogRequestBody && logger.IsEnabled(LogLevel.Debug))
7077
logger.Log(
71-
LogLevel.Trace,
78+
LogLevel.Debug,
7279
EventIds.RequestContent,
7380
new HttpContentLogValue(Kind.Request, request.Content),
7481
null,
7582
(state, ex) => state.ToString());
76-
}
7783
}
7884

79-
public static void RequestEnd(ILogger logger, HttpResponseMessage response, TimeSpan duration)
85+
public static void RequestEnd(CustomLoggingOptions options, ILogger logger, HttpResponseMessage response, TimeSpan duration)
8086
{
81-
_requestEnd(logger, duration.TotalMilliseconds, response.StatusCode, null);
82-
83-
if (logger.IsEnabled(LogLevel.Trace))
87+
if (duration.TotalMilliseconds < options.SlowRequestLoggingThreshold)
8488
{
89+
_requestEnd(logger, duration.TotalMilliseconds, response.StatusCode, null);
90+
}
91+
else
92+
{
93+
_requestEndTooSlow(logger, duration.TotalMilliseconds, response.StatusCode, null);
94+
}
95+
96+
if (options.LogResponseHeader && logger.IsEnabled(LogLevel.Debug))
8597
logger.Log(
86-
LogLevel.Trace,
98+
LogLevel.Debug,
8799
EventIds.ResponseHeader,
88100
new HttpHeadersLogValue(Kind.Response, response.Headers, response.Content?.Headers),
89101
null,
90102
(state, ex) => state.ToString());
91103

104+
if (options.LogResponseBody && logger.IsEnabled(LogLevel.Debug))
92105
logger.Log(
93-
LogLevel.Trace,
106+
LogLevel.Debug,
94107
EventIds.ResponseContent,
95108
new HttpContentLogValue(Kind.Response, response.Content),
96109
null,
97110
(state, ex) => state.ToString());
98-
}
99111
}
100112
}
101113
}

0 commit comments

Comments
 (0)