Skip to content

Movement and Internalization Phase 2 #1626

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Nov 16, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 0 additions & 11 deletions Microsoft.ML.sln
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.ML.CpuMath", "src
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.ML.PipelineInference", "src\Microsoft.ML.PipelineInference\Microsoft.ML.PipelineInference.csproj", "{2D7391C9-8254-4B8F-BF26-FADAF8F02F44}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.ML.InferenceTesting", "test\Microsoft.ML.InferenceTesting\Microsoft.ML.InferenceTesting.csproj", "{E278EC99-E6EE-49FE-92E6-0A309A478D98}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.ML.Data", "src\Microsoft.ML.Data\Microsoft.ML.Data.csproj", "{AD92D96B-0E96-4F22-8DCE-892E13B1F282}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.ML.Onnx", "src\Microsoft.ML.Onnx\Microsoft.ML.Onnx.csproj", "{65D0603E-B96C-4DFC-BDD1-705891B88C18}"
Expand Down Expand Up @@ -175,14 +173,6 @@ Global
{2D7391C9-8254-4B8F-BF26-FADAF8F02F44}.Release|Any CPU.Build.0 = Release|Any CPU
{2D7391C9-8254-4B8F-BF26-FADAF8F02F44}.Release-Intrinsics|Any CPU.ActiveCfg = Release-Intrinsics|Any CPU
{2D7391C9-8254-4B8F-BF26-FADAF8F02F44}.Release-Intrinsics|Any CPU.Build.0 = Release-Intrinsics|Any CPU
{E278EC99-E6EE-49FE-92E6-0A309A478D98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E278EC99-E6EE-49FE-92E6-0A309A478D98}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E278EC99-E6EE-49FE-92E6-0A309A478D98}.Debug-Intrinsics|Any CPU.ActiveCfg = Debug-Intrinsics|Any CPU
{E278EC99-E6EE-49FE-92E6-0A309A478D98}.Debug-Intrinsics|Any CPU.Build.0 = Debug-Intrinsics|Any CPU
{E278EC99-E6EE-49FE-92E6-0A309A478D98}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E278EC99-E6EE-49FE-92E6-0A309A478D98}.Release|Any CPU.Build.0 = Release|Any CPU
{E278EC99-E6EE-49FE-92E6-0A309A478D98}.Release-Intrinsics|Any CPU.ActiveCfg = Release-Intrinsics|Any CPU
{E278EC99-E6EE-49FE-92E6-0A309A478D98}.Release-Intrinsics|Any CPU.Build.0 = Release-Intrinsics|Any CPU
{AD92D96B-0E96-4F22-8DCE-892E13B1F282}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AD92D96B-0E96-4F22-8DCE-892E13B1F282}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AD92D96B-0E96-4F22-8DCE-892E13B1F282}.Debug-Intrinsics|Any CPU.ActiveCfg = Debug-Intrinsics|Any CPU
Expand Down Expand Up @@ -520,7 +510,6 @@ Global
{EC743D1D-7691-43B7-B9B0-5F2F7018A8F6} = {AED9C836-31E3-4F3F-8ABC-929555D3F3C4}
{46F2F967-C23F-4076-858D-33F7DA9BD2DA} = {09EADF06-BE25-4228-AB53-95AE3E15B530}
{2D7391C9-8254-4B8F-BF26-FADAF8F02F44} = {09EADF06-BE25-4228-AB53-95AE3E15B530}
{E278EC99-E6EE-49FE-92E6-0A309A478D98} = {AED9C836-31E3-4F3F-8ABC-929555D3F3C4}
{AD92D96B-0E96-4F22-8DCE-892E13B1F282} = {09EADF06-BE25-4228-AB53-95AE3E15B530}
{65D0603E-B96C-4DFC-BDD1-705891B88C18} = {09EADF06-BE25-4228-AB53-95AE3E15B530}
{707BB22C-7E5F-497A-8C2F-74578F675705} = {09EADF06-BE25-4228-AB53-95AE3E15B530}
Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.ML.Api/GenerateCodeCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace Microsoft.ML.Runtime.Api
///
/// REVIEW: Consider adding support for generating VBuffers instead of arrays, maybe for high dimensionality vectors.
/// </summary>
public sealed class GenerateCodeCommand : ICommand
internal sealed class GenerateCodeCommand : ICommand
{
public const string LoadName = "GenerateSamplePredictionCode";
private const string CodeTemplatePath = "Microsoft.ML.Api.GeneratedCodeTemplate.csresource";
Expand Down
39 changes: 0 additions & 39 deletions src/Microsoft.ML.Api/TypedCursor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -528,8 +528,6 @@ public ICursor GetRootCursor()
/// </summary>
public static class CursoringUtils
{
private const string NeedEnvObsoleteMessage = "This method is obsolete. Please use the overload that takes an additional 'env' argument. An environment can be created via new LocalEnvironment().";

/// <summary>
/// Generate a strongly-typed cursorable wrapper of the <see cref="IDataView"/>.
/// </summary>
Expand All @@ -550,24 +548,6 @@ public static ICursorable<TRow> AsCursorable<TRow>(this IDataView data, IHostEnv
return TypedCursorable<TRow>.Create(env, data, ignoreMissingColumns, schemaDefinition);
}

/// <summary>
/// Generate a strongly-typed cursorable wrapper of the <see cref="IDataView"/>.
/// </summary>
/// <typeparam name="TRow">The user-defined row type.</typeparam>
/// <param name="data">The underlying data view.</param>
/// <param name="ignoreMissingColumns">Whether to ignore the case when a requested column is not present in the data view.</param>
/// <param name="schemaDefinition">Optional user-provided schema definition. If it is not present, the schema is inferred from the definition of T.</param>
/// <returns>The cursorable wrapper of <paramref name="data"/>.</returns>
[Obsolete(NeedEnvObsoleteMessage)]
public static ICursorable<TRow> AsCursorable<TRow>(this IDataView data, bool ignoreMissingColumns = false,
SchemaDefinition schemaDefinition = null)
where TRow : class, new()
{
// REVIEW: Take an env as a parameter.
var env = new ConsoleEnvironment();
return data.AsCursorable<TRow>(env, ignoreMissingColumns, schemaDefinition);
}

/// <summary>
/// Convert an <see cref="IDataView"/> into a strongly-typed <see cref="IEnumerable{TRow}"/>.
/// </summary>
Expand All @@ -589,24 +569,5 @@ public static IEnumerable<TRow> AsEnumerable<TRow>(this IDataView data, IHostEnv
var engine = new PipeEngine<TRow>(env, data, ignoreMissingColumns, schemaDefinition);
return engine.RunPipe(reuseRowObject);
}

/// <summary>
/// Convert an <see cref="IDataView"/> into a strongly-typed <see cref="IEnumerable{TRow}"/>.
/// </summary>
/// <typeparam name="TRow">The user-defined row type.</typeparam>
/// <param name="data">The underlying data view.</param>
/// <param name="reuseRowObject">Whether to return the same object on every row, or allocate a new one per row.</param>
/// <param name="ignoreMissingColumns">Whether to ignore the case when a requested column is not present in the data view.</param>
/// <param name="schemaDefinition">Optional user-provided schema definition. If it is not present, the schema is inferred from the definition of T.</param>
/// <returns>The <see cref="IEnumerable{TRow}"/> that holds the data in <paramref name="data"/>. It can be enumerated multiple times.</returns>
[Obsolete(NeedEnvObsoleteMessage)]
public static IEnumerable<TRow> AsEnumerable<TRow>(this IDataView data, bool reuseRowObject,
bool ignoreMissingColumns = false, SchemaDefinition schemaDefinition = null)
where TRow : class, new()
{
// REVIEW: Take an env as a parameter.
var env = new ConsoleEnvironment();
return data.AsEnumerable<TRow>(env, reuseRowObject, ignoreMissingColumns, schemaDefinition);
}
}
}
3 changes: 2 additions & 1 deletion src/Microsoft.ML.Core/CommandLine/CmdParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ internal enum SettingsFlags
///
/// This allows components to be created by name, signature type, and a settings string.
/// </summary>
public interface ICommandLineComponentFactory : IComponentFactory
[BestFriend]
internal interface ICommandLineComponentFactory : IComponentFactory
{
Type SignatureType { get; }
string Name { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;

namespace Microsoft.ML.Runtime
{
[Obsolete("The usage for this is intended for the internal command line utilities and is not intended for anything related to the API. " +
"Please consider another way of doing whatever it is you're attempting to accomplish.")]
[BestFriend]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe this is the right change for AssemblyLoadingUtils. I purposefully made it as "shared source" between Maml and the ML.Legacy assemblies, with the hopes that ML.Legacy will just go away, so this will only be used in Maml.

I don't think it should be in the Core assembly (and especially not with a [BestFriend] attribute). I don't want people calling this code at all. Maml and ML.Legacy need it to keep things working, but I don't want any other places calling it. I've instructed other internal projects, if they need this code, they can copy it and modify it to meet their needs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, people have been ignoring your instructions. 😄 A couple more now use it.

I made ICommand and all ICommand implementors internal. Things that directly call some of the commands now had to reference them. In the case of Maml this was Legacy and ResultProcessor, both of which actually use this AssemblyLoadingUtils. So I made Maml consider Legacy and ResultProcessor friends of Maml, so that they could keep using it. But of course this results in an error, because they're

However, because you made this a source reference, I then had assemblies referencing each other, which led to name collisions resulting in compiler errors. This was my attempt to untangle the mess. I can't just go back to the way things were because that doesn't compile. I didn't perform this move in a fit of whimsy.

It may be that eventually we can winnow it down, but for right now, I'm not sure what else is better to do.

I'm not sure what you mean about "especially not." Just because something is a best-friend internal doesn't mean we're going to keep it now and forever. Indeed the point of introducing this infrastructure in the first place is so we would be free to later whip the internal infrastructure code into a better form, without compromising v1.0. This I think falls pretty squarely into its intended use.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what you mean about "especially not." Just because something is a best-friend internal doesn't mean we're going to keep it now and forever.

It means more places will feel empowered to call this method, because they won't get a "Don't use this" error. And as more places use it, the harder it will be to remove in the future. (Especially places that aren't in this repo, that are planning on getting IVT the Core assembly)

Can we instead do some other "tricks" to make it not part of the Core assembly? Maybe using extern alias? https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/extern-alias

Or maybe we have compiler directives that change the namespace of this file/class in the different assemblies it is used in?

I'd really like this type not to be in the Core assembly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then I'll mark it obsolete as I did with IHostEnvironment.GetTempFile. That will give people a nice little message discouraging them, without requiring that I introduce special build infrastructure just for this one little file, which frankly I don't want to do.


In reply to: 234269562 [](ancestors = 234269562)

internal static class AssemblyLoadingUtils
{
/// <summary>
Expand Down
6 changes: 4 additions & 2 deletions src/Microsoft.ML.Core/Data/ICommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ namespace Microsoft.ML.Runtime.Command
/// <summary>
/// The signature for commands.
/// </summary>
public delegate void SignatureCommand();
[BestFriend]
internal delegate void SignatureCommand();

public interface ICommand
[BestFriend]
internal interface ICommand
{
void Run();
}
Expand Down
12 changes: 3 additions & 9 deletions src/Microsoft.ML.Core/Data/IFileHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public sealed class SimpleFileHandle : IFileHandle
// handle has been disposed.
private List<Stream> _streams;

private bool IsDisposed { get { return _streams == null; } }
private bool IsDisposed => _streams == null;

public SimpleFileHandle(IExceptionContext ectx, string path, bool needsWrite, bool autoDelete)
{
Expand All @@ -84,15 +84,9 @@ public SimpleFileHandle(IExceptionContext ectx, string path, bool needsWrite, bo
_streams = new List<Stream>();
}

public bool CanWrite
{
get { return !_wrote && !IsDisposed; }
}
public bool CanWrite => !_wrote && !IsDisposed;

public bool CanRead
{
get { return _wrote && !IsDisposed; }
}
public bool CanRead => _wrote && !IsDisposed;

public void Dispose()
{
Expand Down
8 changes: 6 additions & 2 deletions src/Microsoft.ML.Core/Data/IHostEnvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ public interface IHostEnvironment : IChannelProvider, IProgressChannelProvider
/// The suffix and prefix are optional. A common use for suffix is to specify an extension, eg, ".txt".
/// The use of suffix and prefix, including whether they have any affect, is up to the host environment.
/// </summary>
[Obsolete("The host environment is not disposable, so it is inappropriate to use this method. " +
"Please handle your own temporary files within the component yourself, including their proper disposal and deletion.")]
IFileHandle CreateTempFile(string suffix = null, string prefix = null);

/// <summary>
Expand Down Expand Up @@ -188,7 +190,8 @@ public readonly struct ChannelMessage
/// </summary>
public string Message => _args != null ? string.Format(_message, _args) : _message;

public ChannelMessage(ChannelMessageKind kind, MessageSensitivity sensitivity, string message)
[BestFriend]
internal ChannelMessage(ChannelMessageKind kind, MessageSensitivity sensitivity, string message)
{
Contracts.CheckNonEmpty(message, nameof(message));
Kind = kind;
Expand All @@ -197,7 +200,8 @@ public ChannelMessage(ChannelMessageKind kind, MessageSensitivity sensitivity, s
_args = null;
}

public ChannelMessage(ChannelMessageKind kind, MessageSensitivity sensitivity, string fmt, params object[] args)
[BestFriend]
internal ChannelMessage(ChannelMessageKind kind, MessageSensitivity sensitivity, string fmt, params object[] args)
{
Contracts.CheckNonEmpty(fmt, nameof(fmt));
Contracts.CheckNonEmpty(args, nameof(args));
Expand Down
3 changes: 2 additions & 1 deletion src/Microsoft.ML.Core/Data/ProgressReporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ namespace Microsoft.ML.Runtime.Data
/// <summary>
/// The progress reporting classes used by <see cref="HostEnvironmentBase{THostEnvironmentBase}"/> descendants.
/// </summary>
public static class ProgressReporting
[BestFriend]
internal static class ProgressReporting
{
/// <summary>
/// The progress channel for <see cref="ConsoleEnvironment"/>.
Expand Down
6 changes: 4 additions & 2 deletions src/Microsoft.ML.Core/Data/ServerChannel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ namespace Microsoft.ML.Runtime
/// delegates will be published in some fashion, with the target scenario being
/// that the library will publish some sort of restful API.
/// </summary>
public sealed class ServerChannel : ServerChannel.IPendingBundleNotification, IDisposable
[BestFriend]
internal sealed class ServerChannel : ServerChannel.IPendingBundleNotification, IDisposable
{
// See ServerChannel.md for a more elaborate discussion of high level usage and design.
private readonly IChannelProvider _chp;
Expand Down Expand Up @@ -250,7 +251,8 @@ public void AddDoneAction(Action onDone)
}
}

public static class ServerChannelUtilities
[BestFriend]
internal static class ServerChannelUtilities
{
/// <summary>
/// Convenience method for <see cref="ServerChannel.Start"/> that looks more idiomatic to typical
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ namespace Microsoft.ML.Runtime.EntryPoints
/// <summary>
/// This is a signature for classes that are 'holders' of entry points and components.
/// </summary>
public delegate void SignatureEntryPointModule();
[BestFriend]
internal delegate void SignatureEntryPointModule();

/// <summary>
/// A simplified assembly attribute for marking EntryPoint modules.
/// </summary>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public sealed class EntryPointModuleAttribute : LoadableClassAttributeBase
[BestFriend]
internal sealed class EntryPointModuleAttribute : LoadableClassAttributeBase
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make the EntryPoint related methods on ComponentCatalog internal as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, assuredly. Do you feel this PR needs to be longer though? I'm trying to break up the internalization work into multiple phases (hence the numbering, phase 1, phase 2, and so forth). While surely we can just keep going forever, I think it would be more helpful if we tried to iterate quickly, rather than insisting we internalize everything in one gigantic PR. So just pointing out "you could have internalized more," while I'm sure well intentioned, is something I already kind of know and understand?


In reply to: 234256509 [](ancestors = 234256509)

{
public EntryPointModuleAttribute(Type loaderType)
: base(null, typeof(void), loaderType, null, new[] { typeof(SignatureEntryPointModule) }, loaderType.FullName)
Expand Down
3 changes: 2 additions & 1 deletion src/Microsoft.ML.Core/EntryPoints/EntryPointUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@

namespace Microsoft.ML.Runtime.EntryPoints
{
public static class EntryPointUtils
[BestFriend]
internal static class EntryPointUtils
{
private static bool IsValueWithinRange<T>(TlcModule.RangeAttribute range, object obj)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.ML.Core/EntryPoints/IMlState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ namespace Microsoft.ML.Runtime.EntryPoints
/// black box to the graph. The macro itself will then case to the concrete type.
/// </summary>
public interface IMlState
{}
{ }
}
3 changes: 2 additions & 1 deletion src/Microsoft.ML.Core/EntryPoints/ModuleArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ namespace Microsoft.ML.Runtime.EntryPoints
/// This class defines attributes to annotate module inputs, outputs, entry points etc. when defining
/// the module interface.
/// </summary>
public static class TlcModule
[BestFriend]
internal static class TlcModule
{
/// <summary>
/// An attribute used to annotate the component.
Expand Down
9 changes: 6 additions & 3 deletions src/Microsoft.ML.Core/Environment/ConsoleEnvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
#pragma warning disable 420 // volatile with Interlocked.CompareExchange

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
Expand All @@ -15,7 +13,12 @@ namespace Microsoft.ML.Runtime.Data
{
using Stopwatch = System.Diagnostics.Stopwatch;

public sealed class ConsoleEnvironment : HostEnvironmentBase<ConsoleEnvironment>
/// <summary>
/// The console environment. As its name suggests, should be limited to those applications that deliberately want
/// console functionality.
/// </summary>
[BestFriend]
internal sealed class ConsoleEnvironment : HostEnvironmentBase<ConsoleEnvironment>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we can close #1284 with this change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. Added to the description.


In reply to: 234249735 [](ancestors = 234249735)

{
public const string ComponentHistoryKey = "ComponentHistory";

Expand Down
31 changes: 6 additions & 25 deletions src/Microsoft.ML.Core/Environment/HostEnvironmentBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ namespace Microsoft.ML.Runtime.Data
/// Base class for channel providers. This is a common base class for<see cref="HostEnvironmentBase{THostEnvironmentBase}"/>.
/// The ParentFullName, ShortName, and FullName may be null or empty.
/// </summary>
public abstract class ChannelProviderBase : IExceptionContext
[BestFriend]
internal abstract class ChannelProviderBase : IExceptionContext
{
/// <summary>
/// Data keys that are attached to the exception thrown via the exception context.
Expand Down Expand Up @@ -79,42 +80,22 @@ public virtual TException Process<TException>(TException ex)
/// <summary>
/// Message source (a channel) that generated the message being dispatched.
/// </summary>
public interface IMessageSource
[BestFriend]
internal interface IMessageSource
{
string ShortName { get; }
string FullName { get; }
bool Verbose { get; }
}

/// <summary>
/// A <see cref="IHostEnvironment"/> that is also a channel listener can attach
/// listeners for messages, as sent through <see cref="IChannelProvider.StartPipe{TMessage}"/>.
/// </summary>
public interface IMessageDispatcher : IHostEnvironment
{
/// <summary>
/// Listen on this environment to messages of a particular type.
/// </summary>
/// <typeparam name="TMessage">The message type</typeparam>
/// <param name="listenerFunc">The action to perform when a message of the
/// appropriate type is received.</param>
void AddListener<TMessage>(Action<IMessageSource, TMessage> listenerFunc);

/// <summary>
/// Removes a previously added listener.
/// </summary>
/// <typeparam name="TMessage">The message type</typeparam>
/// <param name="listenerFunc">The previous listener function that is now being removed.</param>
void RemoveListener<TMessage>(Action<IMessageSource, TMessage> listenerFunc);
}

/// <summary>
/// A basic host environment suited for many environments.
/// This also supports modifying the concurrency factor, provides the ability to subscribe to pipes via the
/// AddListener/RemoveListener methods, and exposes the <see cref="ProgressReporting.ProgressTracker"/> to
/// query progress.
/// </summary>
public abstract class HostEnvironmentBase<TEnv> : ChannelProviderBase, IHostEnvironment, IDisposable, IChannelProvider, IMessageDispatcher
[BestFriend]
internal abstract class HostEnvironmentBase<TEnv> : ChannelProviderBase, IHostEnvironment, IDisposable, IChannelProvider
where TEnv : HostEnvironmentBase<TEnv>
{
/// <summary>
Expand Down
12 changes: 8 additions & 4 deletions src/Microsoft.ML.Core/Environment/TelemetryMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ namespace Microsoft.ML.Runtime
/// <summary>
/// A telemetry message.
/// </summary>
public abstract class TelemetryMessage
[BestFriend]
internal abstract class TelemetryMessage
{
public static TelemetryMessage CreateCommand(string commandName, string commandText)
{
Expand All @@ -40,7 +41,8 @@ public static TelemetryMessage CreateException(Exception exception)
/// <summary>
/// Message with one long text and bunch of small properties (limit on value is ~1020 chars)
/// </summary>
public sealed class TelemetryTrace : TelemetryMessage
[BestFriend]
internal sealed class TelemetryTrace : TelemetryMessage
{
public readonly string Text;
public readonly string Name;
Expand All @@ -57,7 +59,8 @@ public TelemetryTrace(string text, string name, string type)
/// <summary>
/// Message with exception
/// </summary>
public sealed class TelemetryException : TelemetryMessage
[BestFriend]
internal sealed class TelemetryException : TelemetryMessage
{
public readonly Exception Exception;
public TelemetryException(Exception exception)
Expand All @@ -70,7 +73,8 @@ public TelemetryException(Exception exception)
/// <summary>
/// Message with metric value and it properites
/// </summary>
public sealed class TelemetryMetric : TelemetryMessage
[BestFriend]
internal sealed class TelemetryMetric : TelemetryMessage
{
public readonly string Name;
public readonly double Value;
Expand Down
Loading